#include "Joueur.h"
#include "ListeArme.h"
#include "list_of.hpp"
using namespace std;
using namespace boost::assign;

/**
 * @addtogroup Utilitaires
 * @{
 */

/**************************************************************************//**
 *
 * Sert à fixer les différents niveaux de sorties des fonctions en lisant le
 * fichier CONFIG, placé dans le répertoire courant.
 * Si le fichier a été déplacé ou n'est pas présent, les réglages par défaut
 * seront appliqué et un message d'erreur envoyé à la sortie standard.
 *
 *****************************************************************************/
void OutputLevel()
{
  const unsigned int nbr_niveaux = 9;
  string test[13] =
    { "ALL", "MEM", "DEBUG", "LFUNC", "LINFO", "FUNC", "INFO", "BLANK",
      "PROGRESS", "RELEASE", "WARN", "ERR", "OFF" },
    a_trouver[nbr_niveaux] =
      { "Debug::itsLevel", "Joueur::interne",
	"Joueur::fonction_elementaire_xml",
	"Joueur::fonction_recuperation_xml", "Joueur::fonction_tex",
	"Race::elementaire", "Race::fonction", "Classe::elementaire",
	"Classe::fonction"};
  string ligne, level;
  unsigned int i, j, loc;

  ifstream entree;
  entree.open("CONFIG");
  if (entree.fail())
    warning() << "Réglages par défaut appliqués, fichier de configuration illisible" << endreq;
  else
    {
      while(!entree.eof())
	{
	  getline(entree, ligne);
	  for (i = 0; i < nbr_niveaux; i++)
	    {
	      level = "";
	      loc = ligne.find(a_trouver[i], 0);
	      if (loc != npos)
		{
		  j = ligne.size() - 1;
		  while(ligne[j] != ' ')
		    {
		      level = ligne[j] + level;
		      j--;
		    }
		  for (j = 0; j < 13; j++)
		    {
		      if (test[j] == level)
			break;
		    }
		  switch(i)
		    {
		    case 0:
		      dout.setLevel((DebugLevelType) j);
		      break;
		    case 1:
		    case 2:
		    case 3:
		    case 4:
		      Joueur::setLevel((DebugLevelType) j, i);
		      break;
		    case 5:
		    case 6:
		      Race::setLevel((DebugLevelType) j, i - 4);
		      break;
		    case 7:
		    case 8:
		      Classe::setLevel((DebugLevelType) j, i - 6);
		      break;
		    }
		  debug() << a_trouver[i] << ' ' << level << endreq;
		  break;
		}
	    }
	}
    }
}

/**
 * \}
 */


/******************************************************************************
 *
 * Définitions des attributs 'static'
 *
 *****************************************************************************/

const string Joueur::Aj_Force[30][6] =
  {
    {"$-5$", "$-4$" , "$0.5$"  , "$1.5$"  , "$1$" , "$0\\%$" }, // 1
    {"$-3$", "$-2$" , "$0.5$"  , "$2.5$"  , "$1$" , "$0\\%$" }, // 2
    {"$-3$", "$-1$" , "$2.5$"  , "$5$"    , "$2$" , "$0\\%$" }, // 3
    {"$-2$", "$-1$" , "$5$"    , "$12.5$" , "$3$" , "$0\\%$" }, // 4
    {"$-2$", "$-1$" , "$5$"    , "$12.5$" , "$3$" , "$0\\%$" }, // 5
    {"$-1$", "$0$"  , "$10$"   , "$27.5$" , "$4$" , "$0\\%$" }, // 6
    {"$-1$", "$0$"  , "$10$"   , "$27.5$" , "$4$" , "$0\\%$" }, // 7
    {"$0$" , "$0$"  , "$17.5$" , "$45$"   , "$5$" , "$1\\%$" }, // 8
    {"$0$" , "$0$"  , "$17.5$" , "$45$"   , "$5$" , "$1\\%$" }, // 9
    {"$0$" , "$0$"  , "$20$"   , "$57.5$" , "$6$" , "$2\\%$" }, // 10
    {"$0$" , "$0$"  , "$20$"   , "$57.5$" , "$6$" , "$2\\%$" }, // 11
    {"$0$" , "$0$"  , "$22.5$" , "$70$"   , "$7$" , "$4\\%$" }, // 12
    {"$0$" , "$0$"  , "$22.5$" , "$70$"   , "$7$" , "$4\\%$" }, // 13
    {"$0$" , "$0$"  , "$27.5$" , "$85$"   , "$8$" , "$7\\%$" }, // 14
    {"$0$" , "$0$"  , "$27.5$" , "$85$"   , "$8$" , "$7\\%$" }, // 15
    {"$0$" , "$+1$" , "$35$"   , "$97.5$" , "$9$" , "$10\\%$"}, // 16
    {"$+1$", "$+1$" , "$42.5$" , "$110$"  , "$10$", "$13\\%$"}, // 17
    {"$+1$", "$+2$" , "$55$"   , "$127.5$", "$11$", "$16\\%$"}, // 18
    {"$+3$", "$+7$" , "$242.5$", "$270$"  , "$16$", "$50\\%$"}, // 19
    {"$+3$", "$+8$" , "$267.5$", "$350$"  , "$17$", "$60\\%$"}, // 20
    {"$+4$", "$+9$" , "$317.5$", "$405$"  , "$17$", "$70\\%$"}, // 21
    {"$+4$", "$+10$", "$392.5$", "$485$"  , "$18$", "$80\\%$"}, // 22
    {"$+5$", "$+11$", "$467.5$", "$565$"  , "$18$", "$90\\%$"}, // 23
    {"$+6$", "$+12$", "$617.5$", "$770$"  , "$19$", "$95\\%$"}, // 24
    {"$+7$", "$+14$", "$767.5$", "$875$"  , "$19$", "$99\\%$"}, // 25
    {"$+1$", "$+3$" , "$67.5$" , "$140$"  , "$12$", "$20\\%$"}, // 18 01-50
    {"$+2$", "$+3$" , "$80$"   , "$152.5$", "$13$", "$25\\%$"}, // 18 51-75
    {"$+2$", "$+4$" , "$92.5$" , "$165$"  , "$14$", "$30\\%$"}, // 18 76-90
    {"$+2$", "$+5$" , "$117.5$", "$190$"  , "$15$", "$35\\%$"}, // 18 91-99
    {"$+3$", "$+6$" , "$167.5$", "$240$"  , "$16$", "$40\\%$"}  // 18 100
  };

const string Joueur::Aj_Dexterite[14][3] =
  {
    {"$-6$", "$-6$", "$+5$"}, // 1
    {"$-4$", "$-4$", "$+5$"}, // 2
    {"$-3$", "$-3$", "$+4$"}, // 3
    {"$-2$", "$-2$", "$+3$"}, // 4
    {"$-1$", "$-1$", "$+2$"}, // 5
    {"$0$" , "$0$" , "$+1$"}, // 6
    {"$0$" , "$0$" , "$0$" }, // 7-14
    {"$0$" , "$0$" , "$-1$"}, // 15
    {"$+1$", "$+1$", "$-2$"}, // 16
    {"$+2$", "$+2$", "$-3$"}, // 17
    {"$+2$", "$+2$", "$-4$"}, // 18
    {"$+3$", "$+3$", "$-4$"}, // 19-20
    {"$+4$", "$+4$", "$-5$"}, // 21-23
    {"$+5$", "$+5$", "$-6$"}, // 24-25
  };

const string Joueur::Aj_Const[25][5] =
  {
    {"$-3$"  , "$25\\%$" , "Néant"           , "$30\\%$" , "$-2$"}, // 1
    {"$-2$"  , "$30\\%$" , "Néant"           , "$35\\%$" , "$-1$"}, // 2
    {"$-2$"  , "$35\\%$" , "Néant"           , "$40\\%$" , "$0$" }, // 3
    {"$-1$"  , "$40\\%$" , "Néant"           , "$45\\%$" , "$0$" }, // 4
    {"$-1$"  , "$45\\%$" , "Néant"           , "$50\\%$" , "$0$" }, // 5
    {"$-1$"  , "$50\\%$" , "Néant"           , "$55\\%$" , "$0$" }, // 6
    {"$0$"   , "$55\\%$" , "Néant"           , "$60\\%$" , "$0$" }, // 7
    {"$0$"   , "$60\\%$" , "Néant"           , "$65\\%$" , "$0$" }, // 8
    {"$0$"   , "$65\\%$" , "Néant"           , "$70\\%$" , "$0$" }, // 9
    {"$0$"   , "$70\\%$" , "Néant"           , "$75\\%$" , "$0$" }, // 10
    {"$0$"   , "$75\\%$" , "Néant"           , "$80\\%$" , "$0$" }, // 11
    {"$0$"   , "$80\\%$" , "Néant"           , "$85\\%$" , "$0$" }, // 12
    {"$0$"   , "$85\\%$" , "Néant"           , "$90\\%$" , "$0$" }, // 13
    {"$0$"   , "$88\\%$" , "Néant"           , "$92\\%$" , "$0$" }, // 14
    {"$+1$"  , "$90\\%$" , "Néant"           , "$94\\%$" , "$0$" }, // 15
    {"$+2$"  , "$95\\%$" , "Néant"           , "$96\\%$" , "$0$" }, // 16
    {"$+2/3$", "$97\\%$" , "Néant"           , "$98\\%$" , "$0$" }, // 17
    {"$+2/4$", "$99\\%$" , "Néant"           , "$100\\%$", "$0$" }, // 18
    {"$+2/5$", "$99\\%$" , "Néant"           , "$100\\%$", "$+1$"}, // 19
    {"$+2/5$", "$99\\%$" , "$\\frac{1}{6}$~t", "$100\\%$", "$+1$"}, // 20
    {"$+2/6$", "$99\\%$" , "$\\frac{1}{5}$~t", "$100\\%$", "$+2$"}, // 21
    {"$+2/6$", "$99\\%$" , "$\\frac{1}{4}$~t", "$100\\%$", "$+2$"}, // 22
    {"$+2/6$", "$99\\%$" , "$\\frac{1}{3}$~t", "$100\\%$", "$+3$"}, // 23
    {"$+2/7$", "$99\\%$" , "$\\frac{1}{2}$~t", "$100\\%$", "$+3$"}, // 24
    {"$+2/7$", "$100\\%$", "1~t"             , "$100\\%$", "$+4$"}  // 25
  };

const string Joueur::Aj_Int[19][5] =
  {
    {"$0$"  , "$-$", "$-$"     , "$-$" , "$-$"}, // 1
    {"$1$"  , "$-$", "$-$"     , "$-$" , "$-$"}, // 2-8
    {"$2$"  , "$4$", "$35\\%$" , "$6$" , "$-$"}, // 9
    {"$2$"  , "$5$", "$40\\%$" , "$7$" , "$-$"}, // 10
    {"$2$"  , "$5$", "$45\\%$" , "$7$" , "$-$"}, // 11
    {"$3$"  , "$6$", "$50\\%$" , "$7$" , "$-$"}, // 12
    {"$3$"  , "$6$", "$55\\%$" , "$9$" , "$-$"}, // 13
    {"$4$"  , "$7$", "$60\\%$" , "$9$" , "$-$"}, // 14
    {"$4$"  , "$7$", "$65\\%$" , "$11$", "$-$"}, // 15
    {"$5$"  , "$8$", "$70\\%$" , "$11$", "$-$"}, // 16
    {"$6$"  , "$8$", "$75\\%$" , "$14$", "$-$"}, // 17
    {"$7$"  , "$9$", "$85\\%$" , "$18$", "$-$"}, // 18
    {"$8$"  , "$9$", "$95\\%$" , "Tous", "$1$"}, // 19
    {"$9$"  , "$9$", "$96\\%$" , "Tous", "$2$"}, // 20
    {"$10$" , "$9$", "$97\\%$" , "Tous", "$3$"}, // 21
    {"$11$" , "$9$", "$98\\%$" , "Tous", "$4$"}, // 22
    {"$12$" , "$9$", "$99\\%$" , "Tous", "$5$"}, // 23
    {"$15$" , "$9$", "$100\\%$", "Tous", "$6$"}, // 24
    {"$20$" , "$9$", "$100\\%$", "Tous", "$7$"}  // 29
  };

const string Joueur::Aj_Sagesse[24][4] =
  {
    {"$-6$", "$-$"   , "$80\\%$", "Néant"}, // 1
    {"$-4$", "$-$"   , "$60\\%$", "Néant"}, // 2
    {"$-3$", "$-$"   , "$50\\%$", "Néant"}, // 3
    {"$-2$", "$-$"   , "$45\\%$", "Néant"}, // 4
    {"$-1$", "$-$"   , "$40\\%$", "Néant"}, // 5
    {"$-1$", "$-$"   , "$35\\%$", "Néant"}, // 6
    {"$-1$", "$-$"   , "$30\\%$", "Néant"}, // 7
    {"$0$" , "$-$"   , "$25\\%$", "Néant"}, // 8
    {"$0$" , "$0$"   , "$20\\%$", "Néant"}, // 9
    {"$0$" , "$0$"   , "$15\\%$", "Néant"}, // 10
    {"$0$" , "$0$"   , "$10\\%$", "Néant"}, // 11
    {"$0$" , "$0$"   , "$5\\%$" , "Néant"}, // 12
    {"$0$" , "$1$"   , "$0\\%$" , "Néant"}, // 13-14
    {"$+1$", "$2$"   , "$0\\%$" , "Néant"}, // 15
    {"$+2$", "$2$"   , "$0\\%$" , "Néant"}, // 16
    {"$+3$", "$3$"   , "$0\\%$" , "Néant"}, // 17
    {"$+4$", "$4$"   , "$0\\%$" , "Néant"}, // 18
    {"$+4$", "$1, 3$", "$0\\%$" , ""     }, // 19
    {"$+4$", "$2, 4$", "$0\\%$" , ""     }, // 20
    {"$+4$", "$3, 5$", "$0\\%$" , ""     }, // 21
    {"$+4$", "$4, 5$", "$0\\%$" , ""     }, // 22
    {"$+4$", "$1, 6$", "$0\\%$" , ""     }, // 23
    {"$+4$", "$5, 6$", "$0\\%$" , ""     }, // 24
    {"$+4$", "$6, 7$", "$0\\%$" , ""     }  // 25
  };

const string Joueur::Aj_Charisme[24][3] =
  {
    {"$0$" , "$-8$" , "$-7$" }, // 1
    {"$1$" , "$-7$" , "$-6$" }, // 2
    {"$1$" , "$-6$" , "$-5$" }, // 3
    {"$2$" , "$-5$" , "$-4$" }, // 4
    {"$2$" , "$-4$" , "$-3$" }, // 5
    {"$2$" , "$-3$" , "$-2$" }, // 6
    {"$3$" , "$-2$" , "$-1$" }, // 7
    {"$3$" , "$-1$" , "$0$"  }, // 8
    {"$4$" , "$0$"  , "$0$"  }, // 9-11
    {"$5$" , "$0$"  , "$0$"  }, // 12
    {"$5$" , "$0$"  , "$+1$" }, // 13
    {"$6$" , "$+1$" , "$+2$" }, // 14
    {"$7$" , "$+3$" , "$+3$" }, // 15
    {"$8$" , "$+4$" , "$+5$" }, // 16
    {"$10$", "$+6$" , "$+6$" }, // 17
    {"$15$", "$+8$" , "$+7$" }, // 18
    {"$20$", "$+10$", "$+8$" }, // 19
    {"$25$", "$+12$", "$+9$" }, // 20
    {"$30$", "$+14$", "$+10$"}, // 21
    {"$35$", "$+16$", "$+11$"}, // 22
    {"$40$", "$+18$", "$+12$"}, // 23
    {"$45$", "$+20$", "$+13$"}, // 24
    {"$50$", "$+20$", "$+14$"}  // 25
  };

const ListCapa Joueur::Dons[27] =
  {
    {"Ambidextrie"            , 4},
    {"Artiste"                , 4},
    {"Bagout"                 , 4},
    {"Belle voix"             , 5},
    {"Brio musical"           , 4},
    {"Chance"                 , 6},
    {"Désarticulé"            , 4},
    {"Empathie"               , 4},
    {"Empathie animale"       , 4},
    {"Goût développé"         , 4},
    {"Grâce"                  , 4},
    {"Guérison rapide"        , 6},
    {"Imposture"              , 5},
    {"Mémoire éidétique"      , 4},
    {"Odorat développé"       , 6},
    {"Ouïe développée"        , 5},
    {"Prévision du temps"     , 4},
    {"Résistance à la chaleur", 5},
    {"Résistance au froid"    , 4},
    {"Résistance au poison"   , 6},
    {"Résistance immunitaire" , 5},
    {"Science infuse"         , 4},
    {"Sens de l'orientation"  , 5},
    {"Sommeil léger"          , 5},
    {"Toucher développé"      , 4},
    {"Vigilance"              , 6},
    {"Vision développée"      , 5}
  };

const ListCapa Joueur::Desavantages[38] =
  {
    {"Allergies modérées"       ,  3},
    {"Allergies graves"         ,  8},
    {"Avidité"                  ,  7},
    {"Daltonien"                ,  3},
    {"Ennemi puissant"          , 10},
    {"Fanatisme"                ,  8},
    {"Fragile"                  ,  8},
    {"Gaffeur"                  ,  6},
    {"Honnêteté pathologique"   ,  8},
    {"Lâcheté modérée"          ,  7},
    {"Lâcheté grave"            , 15},
    {"Maladroit modéré"         ,  4},
    {"Maladroit grave"          ,  8},
    {"Malchanceux"              ,  8},
    {"Paresse"                  ,  7},
    {"Pénible"                  ,  6},
    {"Ph. araignées modérée"    ,  5},
    {"Ph. araignée grave"       , 10},
    {"Ph. eau modérée"          ,  6},
    {"Ph. eau grave"            , 12},
    {"Ph. espaces clos modérée" ,  5},
    {"Ph. espaces clos grave"   , 11},
    {"Ph. foule modérée"        ,  4},
    {"Ph. foule grave"          , 10},
    {"Ph. hauteurs modérée"     ,  5},
    {"Ph. hauteurs grave"       , 10},
    {"Ph. magie modérée"        ,  8},
    {"Ph. magie grave"          , 14},
    {"Ph. monstre modérée"      ,  4},
    {"Ph. monstre grave"        ,  9},
    {"Ph. morts-vivants modérée",  8},
    {"Ph. morts-vivants grave"  , 14},
    {"Ph. serpents modérée"     ,  5},
    {"Ph. serpents grave"       , 10},
    {"Ph. ténèbres modérée"     ,  5},
    {"Ph. ténèbres grave"       , 11},
    {"Sommeil lourd"            ,  7},
    {"Susceptible"              ,  6}
  };

const ListNonMart Joueur::CompetencesDiverses[85] =
  {
    // Générales - 35
    {"Agriculture"          , 3, 7,   3, 255, Toutes},
    {"Allumage de feu"      , 2, 8,   3,   4, Toutes},
    {"Brassage"             , 3, 8,   3, 255, Toutes},
    {"Chant"                , 2, 5,   5, 255, Toutes},
    {"Charpenterie"         , 3, 7,   0,   3, Toutes},
    {"Cordonnerie"          , 3, 7,   1,   3, Toutes},
    {"Cuisine"              , 3, 7,   3, 255, Toutes},
    {"Danse"                , 2, 6,   1,   5, Toutes},
    {"Dressage d'animaux"   , 4, 5,   4,   5, Toutes},
    {"Equitation"           , 2, 8,   4,   1, Toutes},
    {"Equitation en vol"    , 4, 5,   4,   1, Toutes},
    {"Etiquette"            , 2, 8,   5,   4, Toutes},
    {"Expertise maritime"   , 3, 8,   1,   4, Toutes},
    {"Forge"                , 4, 6,   0,   3, Toutes},
    {"Héraldique"           , 2, 8,   3, 255, Toutes},
    {"Ingénierie"           , 4, 5,   3,   4, Toutes},
    {"Instrument de musique", 2, 7,   5, 255, Toutes},
    {"Jeu"                  , 2, 5,   4,   3, Toutes},
    {"Langues modernes"     , 2, 9,   3, 255, Toutes},
    {"Maçonnerie"           , 4, 5,   0,   3, Toutes},
    {"Maîtrise des animaux" , 3, 7,   4, 255, Toutes},
    {"Maroquinerie"         , 3, 7,   3,   1, Toutes},
    {"Météorologie"         , 2, 7,   4, 255, Toutes},
    {"Mine"                 , 5, 5,   4,   0, Toutes},
    {"Natation"             , 2, 9,   0, 255, Toutes},
    {"Navigation"           , 3, 6,   3,   4, Toutes},
    {"Orientation"          , 3, 7,   3,   4, Toutes},
    {"Pêche"                , 3, 6,   4,   3, Toutes},
    {"Peinture"             , 3, 7,   1,   4, Toutes},
    {"Petits bateaux"       , 2, 6,   0,   3, Toutes},
    {"Plongée"              , 2, 5,   1,   2, Toutes},
    {"Poterie"              , 3, 7,   1, 255, Toutes},
    {"Sculpture"            , 2, 5,   1,   4, Toutes},
    {"Sixième sens"         , 2, 7,   4, 255, Toutes},
    {"Tailleur"             , 3, 7,   1,   3, Toutes},
    {"Utilis. de cordes"    , 2, 8,   1,   4, Toutes},
    // Combattants - 13
    {"Alpinisme"            , 4, 7,   0,   4, Combattants},
    {"Armurier"             , 5, 5,   3,   0, Combattants},
    //{"Bon équilibre"        , 7,   1, 255, Combattants},
    //{"Camouflage"           , 5,   3, 255, Combattants},
    {"Chasse"               , 2, 7,   4, 255, Combattants},
    {"Combat aveugle"       , 4, 6,   1,   4, Combattants},
    //{"Commandement"         , 6,   5, 255, Combattants},
    {"Conduite de char"     , 4, 5,   1,   4, Combattants},
    {"Conn. des animaux"    , 3, 7,   3,   4, Combattants},
    //{"Coup de pied arrière" , 0, 255, 255, Combattants},
    //{"Coup de pied sauté"   , 5,   0, 255, Combattants},
    //{"Coup redoutable"      , 0, 255, 255, Combattants},
    {"Course"               , 2, 5,   0,   2, Combattants},
    //{"Embuscade"            , 5,   3, 255, Combattants},
    {"Endurance"            , 2, 3,   2, 255, Combattants},
    {"Fab. d'arc et flèches", 5, 6,   3,   1, Combattants},
    {"Forge d'armes"        , 5, 5,   3,   1, Combattants},
    //{"Oeil sûr"             , 0, 255, 255, Combattants},
    //{"Parade de proj."      , 0, 255, 255, Combattants},
    {"Pistage"              , 4, 7,   4, 255, Combattants},
    {"Pose de collets"      , 4, 6,   1,   4, Combattants},
    //{"Rapidité"             , 3,   1, 255, Combattants},
    //{"Rétabliss. instant."  , 7,   1, 255, Combattants},
    //{"Saut"                 , 5,   1, 255, Combattants},
    {"Survie"               , 3, 6,   3,    4, Combattants},
    //{"Volonté de fer"       , 3,   4, 255, Combattants},
    // Magiciens - 10
    {"Astrologie"           , 3, 5,   3,   4, Magiciens},
    {"Astronomie"           , 2, 7,   3, 255, Magiciens},
    {"Conn. des sorts"      , 3, 7,   3, 255, Magiciens},
    {"Cryptographie"        , 3, 6,   3,   4, Magiciens},
    {"Herboristerie"        , 3, 6,   3,   4, Magiciens},
    {"Histoire ancienne"    , 3, 6,   3,   4, Magiciens},
    {"Joaillerie"           , 3, 6,   1, 255, Magiciens},
    {"Langues mortes"       , 4, 5,   3, 255, Magiciens},
    {"Lecture-écriture"     , 2, 8,   3, 255, Magiciens},
    {"Religion"             , 2, 6,   4, 255, Magiciens},
    // Prêtres - 9
    {"Astrologie"           , 3, 5,   3,   4, Pretres},
    {"Conn. des sorts"      , 3, 7,   3, 255, Pretres},
    //{"Coup de pied arrière" , 0, 255, 255, Pretres},
    //{"Coup redoutable"      , 0, 255, 255, Pretres},
    {"Herboristerie"        , 3, 6,   3,   4, Pretres},
    {"Histoire ancienne"    , 3, 6,   3,   4, Pretres},
    {"Histoire locale"      , 2, 8,   3,   5, Pretres},
    {"Langues mortes"       , 4, 5,   3, 255, Pretres},
    {"Lecture-écriture"     , 2, 8,   3, 255, Pretres},
    //{"Parade de proj."      , 0, 255, 255, Pretres},
    {"Premiers secours"     , 4, 5,   5,   4, Pretres},
    {"Religion"             , 2, 6,   4, 255, Pretres},
    //{"Rétabliss. instant."  , 7,   1, 255, Pretres},
    //{"Volonté de fer"       , 3,   4, 255, Pretres},
    // Roublards - 16
    {"Acrobatie"            , 3, 7,   1,   0, Roublards},
    //{"Bon équilibre"        , 7,   1, 255, Roublards},
    //{"Camouflage"           , 5,   3, 255, Roublards},
    {"Combat aveugle"       , 4, 6,   1,   4, Roublards},
    {"Contrefaçon"          , 3, 5,   1,   4, Roublards},
    //{"Coup de pied arrière" , 0, 255, 255, Roublards},
    //{"Coup redoutable"      , 0, 255, 255, Roublards},
    {"Cryptographie"        , 3, 6,   3,   4, Roublards},
    {"Déguisement"          , 4, 5,   5,   4, Roublards},
    //{"Embuscade"            , 5,   3, 255, Roublards},
    {"Evaluation"           , 2, 8,   3,   4, Roublards},
    {"Funambulisme"         , 3, 5,   1, 255, Roublards},
    {"Histoire ancienne"    , 3, 6,   3,   4, Roublards},
    {"Histoire locale"      , 2, 8,   3,   5, Roublards},
    {"Joaillerie"           , 3, 6,   1, 255, Roublards},
    {"Jonglerie"            , 3, 7,   1, 255, Roublards},
    {"Lancer"               , 2, 8,   1,   0, Roublards},
    {"Lire sur les lèvres"  , 3, 7,   3,   4, Roublards},
    //{"Oeil sûr"             , 0, 255, 255, Roublards},
    //{"Parade de proj."      , 0, 255, 255, Roublards},
    {"Pose de collets"      , 3, 6,   1,   4, Roublards},
    //{"Rapidité"             , 3,   1, 255, Roublards},
    //{"Rétabliss. instant."  , 7,   1, 255, Roublards},
    {"Saut"                 , 2, 8,   1,   0, Roublards},
    //{"Saut (mart.)"         , 5,   1, 255, Roublards},
    {"Ventriloquie"         , 4, 5,   3,   5, Roublards}
  };

const string Joueur::CategoriesCompetences[5] = {"Générales", "Combattants",
						 "Magiciens", "Prêtres",
						 "Roublards"};

const map<string, unsigned int> Joueur::GererClasses
= map_list_of("Guerrier", 0)("Paladin", 0)("Rôdeur",0)("Mage", 1)("Spécialiste", 1)("Clerc", 2)("Druide", 3)("Voleur", 4)("Barde", 0);

const vector<unsigned int>* Joueur::CompMartialesParClasse[5] =
  {
    0, &CompMarMage, &CompMarClerc, &CompMarDruide, &CompMarVoleur
  };

const vector<unsigned int> Joueur::CompMarClerc = list_of(6)(46)(47)(48)(49)(50)(52)(53)(55)(133)(134)(137)(138)(141)(142)(143)(154)(155)(156)(157)(162)(165)(166)(167)(168)(169)(170)(180)(183)(191)(194)(197)(198)(203)(204);

const vector<unsigned int> Joueur::CompMarMage = list_of(58)(59)(60)(62)(63)(165)(126)(181)(159)(160)(161)(162);

const vector<unsigned int> Joueur::CompMarDruide = list_of(137)(173)(126)(62)(63)(181)(165);

const vector<unsigned int> Joueur::CompMarVoleur = list_of(137)(62)(63)(126)(0)(58)(59)(60)(61)(192)(18)(181)(97)(98)(91)(165);

DebugLevelType Joueur::fonction_elementaire_xml = BLANK,
  Joueur::fonction_recuperation_xml = BLANK, Joueur::fonction_tex = BLANK,
  Joueur::interne = BLANK;


/******************************************************************************
 *
 * Constructeurs
 * Le constructeur par défaut fait appel au chargement d'un Joueur depuis
 * un fichier .xml
 *
 * FUNC  permet d'afficher le message de fin de lecture du fichier .xml
 *
 *****************************************************************************/
Joueur::Joueur()
  : TAc0(20), PP(0), nb_classes(1), CA(10)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  libere_mem = true;
  /*
   * J_race et J_classe sont alloué dynamiquement, il faudra donc libérer
   * la mémoire
   */
  index = 0;

  string poubelle, nom_fichier;
  ifstream entree;
  bool pb_ouverture;
  do
    {
      blank() << "Entrer le nom du fichier à ouvrir : " << flush;
      getline(cin, nom_fichier);
      nom_fichier = "XML/" + nom_fichier + ".xml";
      entree.open(nom_fichier.c_str());
      pb_ouverture = entree.fail();
      if (pb_ouverture)
	{
	  warning() << "Vérifier le nom du fichier : " << nom_fichier << " invalide." << endreq;
	  cin.clear();
	  getline(cin, poubelle);
	  entree.clear();
	}
    }
  while(pb_ouverture);
  /*
   * Ouvrir un fichier "entree"  en lecture, avec les précautions d'usage ;-)
   *
   * Maintenant, il faut convertir le fichier en une longue string
   */
  blank() << "Lecture du fichier " << nom_fichier << " en cours" << endreq;
  string temp, convert;
  while(!entree.fail())
    {
      getline(entree,temp);
      convert += temp; //pas besoin de saut de ligne
    }
  entree.close();

  func() << "Fichier fermé, lecture terminée" << endreq;

  trouver_interpreter_ecrire_joueur(convert);

  blank() << "Lecture du personnage terminée" << endreq;

  unsigned int TAc0_tmp(20);
  for (unsigned int i(0); i < nb_classes; i++)
    {
      if (J_classe[i]->calcule_TAc0() < TAc0_tmp)
	TAc0_tmp = J_classe[i]->calcule_TAc0();
    }
  TAc0 = TAc0_tmp;
  CA = 10;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Ce constructeur sert lors de la création d'un nouveau Joueur. Dans ce cas
 * la Classe et la Race sont déterminés avant.
 *
 *****************************************************************************/
Joueur::Joueur(Classe* classe, Race* race, const string& nom)
  : J_race(race), TAc0(20), PP(0), nb_classes(1), CA(10)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  Nom = nom;
  libere_mem = false;
  J_classe.push_back(classe);
  TM_switch = Non;

  vector<TypeClasse> tmpTC;
  tmpTC = classe -> get_TC();

  J_CompAccess.assign(tmpTC.begin(),tmpTC.end());

  debug() << "Compétences accessibles paramétrées" << endreq;

  ifstream script_entree;
  script_entree.open("Joueur0/Creation.csh");
  ofstream script_sortie;
  script_sortie.open("tmp.csh");
  string ligne;
  unsigned int loc;

  while (!script_entree.eof())
    {
      getline(script_entree, ligne);
      loc = ligne.find("@", 0);
      if (loc != npos)
	ligne.replace(loc, 1, convert_nom());
      debug() << ligne << endreq;
      script_sortie << ligne << endl;
    }

  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Le destructeur libère au besoin la mémoire allouée dynamiquement
 *
 *****************************************************************************/
Joueur::~Joueur()
{
  if (libere_mem)
    {
      delete J_race;
      for (unsigned int i(0); i < nb_classes; i++)
	delete J_classe[i];
    }
}


/******************************************************************************
 *
 * Effectue l'affichage des informations sur le Joueur
 *
 *****************************************************************************/
void Joueur::information()
{
  blank() << Nom << endreq;
  J_race->affiche_info();
  for (unsigned int i(0); i < nb_classes; i++)
    J_classe[i]->afficher_stats();
}


/******************************************************************************
 *
 * Méthode générique pour demander le nom d'un fichier. L'extension est
 * gérée par la fonction d'appel à demander_nom()
 *
 *****************************************************************************/
string Joueur::demander_nom() const
{
  string ret;
  blank() << "Entrer le nom du fichier (sans extension) : " << flush;
  getline(cin, ret);
  blank() << endreq;
  return ret;
}

/******************************************************************************
 *
 * Sauve les données du Joueur dans un fichier .xml
 *
 * FUNC  permet d'afficher l'état d'avancement de l'écriture
 *
 *****************************************************************************/
void Joueur::ecrire_xml() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Joueur::ecrire_xml -> début" << endreq;
  string nom_fichier, poubelle;
  ofstream sortie;
  bool test;
  getline(cin, poubelle);
  do
    {
      nom_fichier = demander_nom();
      nom_fichier = "XML/" + nom_fichier + ".xml";
      sortie.open(nom_fichier.c_str());
      test = sortie.fail();
      if (test)
	{
	  warning() << "Vérifier le nom du fichier : " << nom_fichier
		     << endreq;
	  cin.clear();
	  sortie.clear();
          getline(cin, poubelle);
	}
    }
  while(test);
  func() << "Fichier ouvert" << endreq;
  
  sortie << "<Joueur>" << endl;
  sortie << "  <Nom> " << Nom << " </Nom>" <<endl;
  sortie << "  <Info_Raciales>" << endl;
  sortie << "    <Race> " << J_race->get_Type() << " </Race>" << endl;
  sortie << "    <Capacites> ";
  unsigned int taille(J_race->get_taille()), i;
  for (i = 0; i< taille; i++)
    sortie << J_race->get_capa(i) << ' ';
  sortie << "</Capacites>" << endl;
  sortie << "  </Info_Raciales>" << endl;
  func() << "Race écrite" << endreq;
  sortie << "  <Traits> ";
  for (i = 0; i< 7; i++)
    sortie << J_classe[0]->get_trait(i) << ' ';
  sortie << "</Traits>" << endl;
  func() << "Traits OK" << endreq;
  sortie << "  <Info_Classe>" << endl;
  sortie << "    <Multi> " << nb_classes << " </Multi>" << endl;
  sortie << "    <PV> " << PV << " </PV>" << endl;
  sortie << "    <PP> " << PP << " </PP>" << endl;
  sortie << "    <Acces> ";
  taille = J_CompAccess.size();
  for (i = 0; i < taille; i++)
    sortie << J_CompAccess[i] << " ";
  sortie << "</Acces>" << endl;
  func() << "On commence à écrire les classes" << endreq;
  for (i = 0; i < nb_classes; i++)
    {
      sortie << "    <Classe> " << J_classe[i]->get_classe() << " </Classe>"
	     << endl;
      sortie << "    <XP> " << J_classe[0]->get_XP() << " </XP>" << endl;
      sortie << "    <Competences> ";
      taille = J_classe[i]->get_combien();
      for (unsigned int j(0); j < taille; j++)
	sortie << J_classe[i] -> get_comp(j) << ' ';
      sortie << "</Competences>" << endl;
      sortie << "    <Sorts> ";
      taille = J_classe[i] -> get_combien_sorts();
      for (unsigned int j(0); j < taille; j++)
	sortie << J_classe[i] -> get_sort(j) << ' ';
      sortie << "</Sorts>" << endl;
      lfunc() << "Classe " << i << " écrite" << endreq;
    }
  func() << "Classe(s) écrite(s)" << endreq;
  sortie << "  </Info_Classe>" << endl;
  sortie << " <Dons> ";
  taille = J_Dons.size();
  for (i = 0; i < taille; i++)
    sortie << J_Dons[i] << ' ';
  sortie << "</Dons>" << endl;
  sortie << " <Desavantages> ";
  taille = J_Desavantages.size();
  for (i = 0; i < taille; i++)
    sortie << J_Desavantages[i] << ' ';
  sortie << "</Desavantages>" << endl;
  sortie << " <Non-martiales> ";
  taille = J_CompDiv.size();
  for (i = 0; i < taille; i++)
    sortie << J_CompDiv[i] << ' ';
  sortie << "</Non-martiales>" << endl;
  sortie << " <Martiales> ";
  taille = J_Martiales.size();
  for (i = 0; i < taille; i++)
    sortie << J_Martiales[i] << ' ';
  sortie << "</Martiales>" << endl;
  sortie << "</Joueur>" << endl;
  sortie.close();
  func() << "Fichier " << nom_fichier << " sauvé" << endreq;
  func() << "Joueur::ecrire_xml -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Fixe le nombre de pp du Joueur, à la création
 *
 *****************************************************************************/
void Joueur::set_pp(const unsigned int& pps)
{
  PP = pps;
  modificateur_PP();
}

/******************************************************************************
 *
 * Fixe le nombre de pv du Joueur, à la création
 *
 *****************************************************************************/
void Joueur::set_pv(const unsigned int& pv)
{
  PV = pv;
}

/******************************************************************************
 *
 * Sert à ajoutter une Classe, gestion du multiclassé lors de la création, de
 * la classe jumelée lors du jumelage.
 *
 *****************************************************************************/
void Joueur::ajout_classe(Classe* classe)
{
  J_classe.push_back(classe);
  nb_classes++;
  if (J_race->get_Type() == "Humain")
    TM_switch = Jum;
  // Un Humain ne peut être que jumelé
  else
    TM_switch = Mul;
  // Un non-humain ne peut être que multiclassé

  J_CompAccess.insert(J_CompAccess.end(), classe -> get_TC().begin(),
		      classe -> get_TC().end());

  nettoie_TC();
}

/******************************************************************************
 *
 * Fonctions de sortie en .tex
 * Pour plus de modularité, on fait appel à des fonctions spécifiques pour
 * chaque fichier .tex à écrire.
 *
 * FUNC  permet d'afficher les fichiers .tex écrits
 * DEBUG permet de vérifier la création du script
 *
 *****************************************************************************/
void Joueur::ecrire_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  /* 
   * Initialisation : on édite un script shell qui va faire le boulot de
   * compilation une fois tous les fichiers créés
   */
  ifstream script_entree;
  script_entree.open("Joueur0/Finition.csh");
  ofstream script_sortie;
  script_sortie.open("tmp.csh");
  string ligne;
  unsigned int loc;

  while (!script_entree.eof())
    {
      getline(script_entree, ligne);
      loc = ligne.find("@", 0);
      if (loc != npos)
	ligne.replace(loc, 1, convert_nom());
      debug() << ligne << endreq;
      script_sortie << ligne << endl;
    }
  
  script_entree.close();
  script_sortie.close();

  ecrire_traits_tex();
  func() << "Traits                   [ OK ]" << endreq;
  ecrire_JS_tex();
  func() << "JS                       [ OK ]" << endreq;
  ecrire_scores_tex();
  func() << "Scores                   [ OK ]" << endreq;
  ecrire_race_tex();
  func() << "Race                     [ OK ]" << endreq;
  ecrire_classe_tex();
  func() << "Classe                   [ OK ]" << endreq;
  ecrire_comp_tex();
  func() << "Compétences              [ OK ]" << endreq;
  ecrire_sorts_tex();
  func() << "Sorts                    [ OK ]" << endreq;
  blank() << "Feuille de personnage écrite" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Donne le nombre de dons
 * 
 *****************************************************************************/
unsigned int Joueur::get_combien_dons() const
{
  return J_Dons.size();
}

/******************************************************************************
 *
 * Donne le nombre de désavantages
 * 
 *****************************************************************************/
unsigned int Joueur::get_combien_desavantages() const
{
  return J_Desavantages.size();
}

/******************************************************************************
 *
 * Donne le nombre de compétences non martiales
 * 
 *****************************************************************************/
unsigned int Joueur::get_combien_competences() const
{
  return J_CompDiv.size();
}

/******************************************************************************
 *
 * Donne le nombre de compétences martiales
 * 
 *****************************************************************************/
unsigned int Joueur::get_combien_comp_martiales() const
{
  return J_Martiales.size();
}

/******************************************************************************
 *
 * Permet de fixer les niveaux de sorties des différentes fonctions
 * 
 *****************************************************************************/
void Joueur::setLevel(const DebugLevelType& level, const unsigned int& n)
{
  switch(n)
    {
    case 1:
      interne = level;
      break;
    case 2:
      fonction_elementaire_xml = level;
      break;
    case 3:
      fonction_recuperation_xml = level;
      break;
    case 4:
      fonction_tex = level;
      break;
    default:
      warning() << "Variable inconnue, dans Joueur::setLevel" << endreq;
    }
}

/******************************************************************************
 *
 * Regarde si le Joueur possède des sorts de mage (=> mage, spécialiste,
 * barde avec compétence) et remplit vec avec les pointeurs sur les classe
 * possédant de tels sorts
 *
 * FUNC  permet d'afficher un message au début et à la fin de la méthode
 * DEBUG permet d'afficher toutes les classes
 *
 *****************************************************************************/
string Joueur::a_sorts_mage(vector<Classe *>& vec) const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Joueur::a_sorts_mage -> début" << endreq;
  unsigned int i, nbr_capa;
  string quoi, retour("");

  vec.clear();

  for(i = 0; i < nb_classes; i++)
    {
      quoi = J_classe[i] -> get_classe();
      debug() << quoi << endreq;
      if (quoi == "Mage" || quoi == "Spécialiste")
	vec.push_back(J_classe[i]);
      else if (quoi == "Barde")
	{
	  nbr_capa = J_classe[i] -> get_combien();
	  for (unsigned int j(0); j < nbr_capa; j++)
	    {
	      if (J_classe[i] -> get_comp(j) == 12)
		{
		  vec.push_back(J_classe[i]);
		  break;
		}
	    }
	}
    }

  if (!vec.empty())
    retour = Nom;

  func() << "Joueur::a_sorts_mage -> fin" << endreq;
  dout.setLevel(etat_precedent);

  return retour;
}

/******************************************************************************
 *
 * Sert à ajouter dons ou désavantages
 * 
 * DEBUG permet d'afficher le contrôle Dons / Désavatages 
 *
 *****************************************************************************/
void Joueur::determiner_dons_desavantages(const TypeComp& quoi)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Joueur::determiner_dons_desavantages -> début" << endreq;
  const ListCapa *liste;
  vector<unsigned int>* vec;
  unsigned int taille, i, save_PP(PP), vec_taille;
  bool ok(true), desav;
  switch(quoi)
    {
    case Don:
      debug() << "Joueur::determiner_dons_desavantages => don" << endreq;
      liste = &Dons[0];
      vec = &J_Dons;
      taille = 27;
      desav = false;
      break;
    case Desav:
      debug() << "Joueur::determiner_dons_desavantages => désavantage"
		  << endreq;
      liste = &Desavantages[0];
      vec = &J_Desavantages;
      taille = 38;
      desav = true;
      break;
    default:
      warning() << "Joueur::determiner_dons_desavantages => inconnu" << endreq;
      ok = false;
      taille = 0;
      break;
    }
  debug() << "nbr " << taille << endreq;
  
  unsigned int nbr;
  bool test(true), encore(false);
  
  if (ok)
    {
      blank() << setfill('*') << setw(56) << '*' << endreq;
      for (i = 0; i < taille; i++, liste++)
	blank() << i+1 << ' ' << liste -> Capa
		    << " (" << liste -> Cout << " pp)" << endreq;
      blank() << i+1 << " Aucune" << endreq;
      
      liste -= taille;
      
      do
	{
	  while(test)
	    {
	      blank() << '(' << PP << " pp restants) " << flush;
	      cin >> nbr;
	      if (nbr!=taille+1)
		{
		  
		  if (PP >= (liste + nbr - 1) -> Cout || desav)
		    {
		      switch(quoi)
			{
			case Don:
			  PP -= (liste + nbr - 1) -> Cout;
			  break;
			case Desav:
			  PP += (liste + nbr - 1) -> Cout;
			  break;
			}
		      vec -> push_back(nbr-1);
		      blank() << "Choisi : "
				  << (liste + nbr - 1) -> Capa << endreq;
		    }
		  else
		    blank() << "Pas assez de pp" << endreq;
		  
		}
	      else
		test = false;
	    }
	  vec_taille = vec -> size();
	  for (i = 0; i < vec_taille; i++)
	    blank() << i + 1 << " " << (liste + (*vec)[i]) -> Capa << endreq;
	  blank() << endreq <<  "1 pour continuer, 2 pour recommencer" << endreq;
	  nbr = demander_unsigned_borne("Choix ", 1, 2);
	  if (nbr == 2)
	    {
	      PP = save_PP;
	      vec -> clear();
	      test = true;
	      encore = true;
	      blank() << endreq;
	    }
	  else
	    encore = false;
	}
      while(encore);
      blank() << endreq << setfill('*') << setw(56) << '*' << endreq;
    }
  func() << "Joueur::determiner_dons_desavantages -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Sert à rajoutter des compétences diverses
 *
 * Il faut mettre encore qqch pour gérer si la compétence qu'on veut
 * rajouter est déjà prise
 *
 *****************************************************************************/
void Joueur::determiner_competences()
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Joueur::determiner_competences -> début" << endreq;
  unsigned int taille(83), i, nbr, tot(J_CompAccess.size());
  bool test(true), encore(false);
  unsigned int t_1, t_2, tmp, save_PP(PP), vec_taille, supplement, quelle,
    inf(100), sup(0);
  vector<unsigned int> temp_vec;

  vector<TypeClasse>::const_iterator Begin(J_CompAccess.begin()),
    End(J_CompAccess.end());

  debug() << "nbr catégories comp non-martiales : " << tot << endreq;
  
  do
    {
      do
	{
	  blank() << endl <<"Catégories de compétences non martiales :"
		      << endreq;
	  for (i = 0; i < 5; i++)
	    {
	      blank() << i + 1 << " " << CategoriesCompetences[i];
	      if (find(Begin, End, (TypeClasse)i) != End)
		blank() << endreq;
	      else
		blank() << "  - cout supplémentaire 5pp" << endreq;
	    }
	  blank() << "6 Sortir" << endreq;
	  
	  quelle = demander_unsigned_borne("Quelle catégorie de compétence ? ",
					   1, 6);
	  blank() << endreq;
	  inf = 100;
	  sup = 0;
	  
	  if (quelle == 6)
	    break;
	  
	  if (find(Begin, End, (TypeClasse)(quelle - 1)) != End)
	      supplement = 0;
	  else
	      supplement = 5;
	  
	  for (i = 0; i < taille; i++)
	    {
	      if (CompetencesDiverses[i].Cl_Admise != (TypeClasse)(quelle - 1))
		continue;
	      if (i + 1 < inf) inf = i + 1;
	      if (i + 1 > sup) sup = i + 1;
	      blank() << i+1 << ' ' << CompetencesDiverses[i].Comp
			  << " (" << CompetencesDiverses[i].Cout + supplement
			  << " pp)" << endreq;
	    }
	  blank() << sup + 1 << " Retour" << endreq;
	  
	  do
	    {
	      nbr = demander_unsigned_borne("("+write_int(PP)+" pp restants) ", inf,
					    sup + 1);
	      
	      if (nbr != sup + 1)
		{
		  if (PP >= CompetencesDiverses[nbr-1].Cout + supplement)
		    {
		      PP -= (CompetencesDiverses[nbr-1].Cout + supplement);
		      temp_vec.push_back(nbr-1);
		      temp_vec.push_back(CompetencesDiverses[nbr-1].Valeur);
		      t_1 = CompetencesDiverses[nbr-1].Trait1;
		      t_2 = CompetencesDiverses[nbr-1].Trait2;
		      if (t_1 != 255 && t_2 != 255)
			{
			  if (J_classe[0] -> get_trait(t_1) < J_classe[0] -> get_trait(t_2))
			    tmp = J_classe[0] -> get_trait(t_2);
			  else
			    tmp = J_classe[0] -> get_trait(t_1);
			}
		      else if (t_1 != 255)
			tmp = J_classe[0] -> get_trait(t_1);
		      modificateur_val(temp_vec.back(), tmp);
		      blank() << "Compétence non-martiale choisie : "
				  << CompetencesDiverses[nbr-1].Comp << endreq;
		    }
		  else
		    blank() << "Pas assez de pp" << endreq;
		}
	    }
	  while (nbr != sup + 1);
	}
      while (true);
      vec_taille = temp_vec.size();
      for (i = 0; i < vec_taille; i+=2)
	blank() << (i / 2) + 1 << " "
		    << CompetencesDiverses[temp_vec[i]].Comp << " "
		    << temp_vec[i + 1] <<  endreq;
      blank() << endreq <<  "1 pour continuer, 2 pour recommencer"
		  << endreq;
      nbr = demander_unsigned_borne("Choix ", 1, 2);
      if (nbr == 2)
	{
	  PP = save_PP;
	  temp_vec.clear();
	  test = true;
	  encore = true;
	  blank() << endreq;
	}
      else
	encore = false;
    }
  while (encore);

  J_CompDiv.insert(J_CompDiv.end(), temp_vec.begin(), temp_vec.end());

  blank() << endl << setfill('*') << setw(56) << '*' << endreq;
  func() << "Joueur::determiner_competences -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Sert à augmenter les compétences non-martiales, c'est à dire permet
 * l'augmentation des talent.
 *
 *****************************************************************************/
void Joueur::augmenter_competences()
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Joueur::augmenter_competences -> début" << endreq;

  unsigned int taille(get_combien_competences()), i, nbr, derniere, combien,
    save_PP(PP);
  bool test(true), encore(false);
  vector<unsigned int> temp_vec; // copie temporaire
  temp_vec.assign(J_CompDiv.begin(), J_CompDiv.end());

  for(i = 0; i < taille; i+=2)
    blank() << i / 2 + 1 << " " << CompetencesDiverses[J_CompDiv[i]].Comp
		<< " " << J_CompDiv[i+1] << endreq;

  derniere = (taille + 1) / 2 + 1;
  blank() << derniere << " Terminé" << endreq;

  do
    {
      do
	{
	  nbr = demander_unsigned_borne("Quelle compétence améliorer ? (" +
					write_int(PP) + " PP restants) ",
					1, derniere);
	  if (nbr == derniere)
	    test = false;
	  else if (PP == 0)
	    test = false;
	  else
	    {
	      combien = demander_unsigned_borne("De combien ? ", 1, PP);
	      temp_vec[(nbr - 1) * 2 + 1] += combien;
	      PP -= combien;
	    }
	  if (PP == 0)
	    test = false;
	}
      while(test);
    
      for(i = 0; i < taille; i+=2)
	blank() << i / 2 + 1 << " "
		    << CompetencesDiverses[J_CompDiv[i]].Comp << " "
		    << J_CompDiv[i+1] << " -> " << temp_vec[i+1] << endreq;
      
      blank() << endreq <<  "1 pour continuer, 2 pour recommencer" << endreq;
      nbr = demander_unsigned_borne("Choix ", 1, 2);
      if (nbr == 2)
	{
	  PP = save_PP;
	  test = true;
	  encore = true;
	  temp_vec.clear();
	  temp_vec.assign(J_CompDiv.begin(), J_CompDiv.end());
	  blank() << endreq;
	}
      else
	encore = false;
    }
  while(encore);

  J_CompDiv.clear();
  J_CompDiv.assign(temp_vec.begin(), temp_vec.end());
  
  func() << "Joueur::augmenter_competences -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Sert à déterminer les compétences martiales
 *
 *****************************************************************************/
void Joueur::determiner_comp_martiales()
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Joueur::determiner_comp_martiales -> début" << endreq;

  unsigned int i, taille(J_classe.size());

  bool tout_dispo(false);

  map<string, unsigned int> acces;

  string tmpClasse;

  for (i = 0; i < taille; i++)
    {
      tmpClasse = J_classe[i] -> get_classe();
      if (tmpClasse == "Guerrier" || tmpClasse ==  "Rôdeur" ||
	  tmpClasse == "Paladin")
	tout_dispo = true;
      J_classe[i] -> get_prix_acces(&acces);
    }

  if (tout_dispo)
    info() << "Possibilité d'apprendre des groupes de compétences" << endreq;

  map<string, unsigned int>::const_iterator mapIt, mapBegin(acces.begin()),
    mapEnd(acces.end());

  for (mapIt = mapBegin; mapIt != mapEnd; mapIt++)
    lfunc() << setfill(' ') << setw(11) << left << mapIt -> first
	    << " -> " << mapIt -> second << " pp" << endreq;

  unsigned int quelle, nbr, inf, sup, prix(100), vec_taille, save_PP(PP), quoi;
  bool encore(true), test(false);
  vector<unsigned int> temp_vec;
  const vector<unsigned int>* ptr;

  do
    {
      do
	{
	  blank() << endl <<"Catégories de compétences martiales :"
		  << endreq;
	  for (i = 0; i < 12; i++)
	    {
	      blank() << i + 1 << " " << GroupesLarges[i].nom <<  endreq;
	    }
	  blank() << "14 Sortir" << endreq;
	  
	  quelle = demander_unsigned_borne("Quelle catégorie de compétence ? ",
					   1, 14);
	  blank() << endreq;
	  inf = 210;
	  sup = 0;
	  
	  if (quelle == 14)
	    break;
	  
	  taille = GroupesLarges[quelle - 1].restreints;

	  if (taille == 0)
	    {
	      /*
	       * Ici on traite les groupes restreints qui n'appartiennent
	       * pas à un groupe large, càd les arbalètes, arcs, etc
	       */
	      for (i = 0; i < 205; i++)
		{
		  if (Toutes_armes[i].groupe_large != (quelle - 1))
		    continue;
		  if (i + 1 < inf) inf = i + 1;
		  if (i + 1 > sup) sup = i + 1;
		  if (Toutes_armes[i].Nom_arme.substr(0, 1) == "-")
		    continue;
		  blank() << i+1 << ' ' << Toutes_armes[i].Nom_arme << endreq;
		}
	      blank() << sup + 1 << " Retour" << endreq;
	  
	    }
	  else
	    {
	      /*
	       * Maintenant on s'occupe des groupes larges. Dans un premier
	       * temps on choisi un groupe restreint, qui sera ensuite
	       * affiché comme dans le cas précédent.
	       */
	      for (i = 0; i < taille; i++)
		blank() << i + 1 << ' ' << GroupesRestreints[quelle-1][i]
			<< endreq;
	      blank() << taille + 1 << " Sortir" << endreq;
	  
	      quoi = demander_unsigned_borne("Quelle catégorie de compétence ? ",
					       1, taille + 1);
	      blank() << endreq;

	      if (quoi == taille + 1)
		break;

	      if (quoi == taille)
		quoi = 0;

	      for (i = 0; i < 205; i++)
		{
		  if (Toutes_armes[i].groupe_large != (quelle - 1))
		    continue;
		  if  (Toutes_armes[i].groupe_restreint != (quoi))
		    continue;
		  if (i + 1 < inf) inf = i + 1;
		  if (i + 1 > sup) sup = i + 1;
		  if (Toutes_armes[i].Nom_arme.substr(0, 1) == "-")
		    continue;
		  blank() << i + 1 << ' ' << Toutes_armes[i].Nom_arme << endreq;
		}
	      blank() << sup + 1 << " Retour" << endreq;
	    }

	  // Mais à partir de là c'est de nouveau commun, ouf!
	  do
	    {
	      nbr = demander_unsigned_borne("("+write_int(PP)+" pp restants) ",
					    inf, sup + 1);
	      
	      if (nbr != sup + 1)
		{
		  prix = 20;
		  for (mapIt = mapBegin; mapIt != mapEnd; mapIt++)
		    {
		      tmpClasse = mapIt -> first;
		      lfunc() << "On cherche " << tmpClasse << endreq;
		      ptr = CompMartialesParClasse[GererClasses.find(tmpClasse) -> second];
		      
		      if (ptr == 0)
			// Combattants => on l'a de toute façon
			{
			  debug() << "Prix = " << mapIt -> second << endreq;
			  if (mapIt -> second < prix)
			    prix = mapIt -> second;
			}
		      else if (find(ptr -> begin(), ptr -> end(), nbr - 1) != ptr -> end())
			{
			  debug() << "Prix = " << mapIt -> second << endreq;
			  if (mapIt -> second < prix)
			      prix = mapIt -> second;;
			}
		    }
		  if (prix != 20)
		    {
		      linfo() << "Prix final : " << prix << endreq;
		      // Chercher coût ici
		      if (PP >= prix)
			{
			  if (!(safe_push_back(&J_Martiales, nbr - 1)
				&& safe_push_back(&temp_vec, nbr - 1)))
			    {
			      temp_vec.push_back(nbr - 1);
			      PP -= prix;
			    }
			  else
			    warning() << "Compétence déjà prise" << endreq;
			}
		      else
			blank() << "Pas assez de pp" << endreq;
		    }
		  else
		    blank() << "Compétence inaccessible" << endreq;
		}
	    }
	  while (nbr != sup + 1);
	}
      while (true);
      vec_taille = temp_vec.size();
      for (i = 0; i < vec_taille; i++)
	blank() << i + 1 << " "
		<< Toutes_armes[temp_vec[i]].Nom_arme <<  endreq;
      blank() << endreq <<  "1 pour continuer, 2 pour recommencer"
	      << endreq;
      nbr = demander_unsigned_borne("Choix ", 1, 2);
      if (nbr == 2)
	{
	  PP = save_PP;
	  temp_vec.clear();
	  test = true;
	  encore = true;
	  blank() << endreq;
	}
      else
	encore = false;
    }
  while (encore);

  J_Martiales.insert(J_Martiales.end(), temp_vec.begin(), temp_vec.end());

  func() << "Joueur::determiner_comp_martiales -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Permet la progression en XP du personnage
 *
 * FUNC  permet d'afficher le nombre d'xp avant - après
 * DEBUG permet d'afficher l'état multi / jumelé / single classe
 *
 *****************************************************************************/
void Joueur::ajouter_xp(const unsigned int& xp)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  unsigned int a_distribuer, tmp_niv, pv_gagnes(0);
  debug() << "nb_classes = " << nb_classes << endreq;
  switch(TM_switch)
    {
    case Non:
      func() << "Pas de classes multiples" << endreq;
      func() << "Avant : " << J_classe.back() -> get_XP() << endreq;
      tmp_niv = J_classe.back() -> get_Niveau();
      a_distribuer = xp;
      J_classe.back() -> augmenter_xp(a_distribuer);
      if (tmp_niv != J_classe.back() -> get_Niveau())
	{
	  blank() << "Tu passes un niveau!" << endreq;
	  pv_gagnes = demander_unsigned("Entrer le nombre de PV obtenus : ");
	  ajouter_pv(pv_gagnes);
	  J_classe.back() -> augmenter_talents(0, true);
	  // mettre ici l'augmentation des talents de voleurs
	}
      debug() << "Après : " << J_classe.back() -> get_XP() << endreq;
      break;
    case Mul:
      func() << "Perso multiclassé" << endreq;
      debug() << "Avant : " << J_classe.back() -> get_XP() << endreq;      
      a_distribuer = xp / nb_classes;
      for (unsigned int i(0); i < nb_classes; i++)
	{
	  tmp_niv = J_classe[i] -> get_Niveau();
	  J_classe[i] -> augmenter_xp(a_distribuer);
	  if (tmp_niv != J_classe[i] -> get_Niveau())
	    {
	      blank() << "Tu passes un niveau de "
			  << J_classe[i] -> get_classe() <<"!" << endreq;
	      pv_gagnes = demander_unsigned("Entrer le nombre de PV obtenus");
	      ajouter_pv(pv_gagnes);
	      J_classe[i] -> augmenter_talents(0, true);
	    }
	}
      debug() << "Après : " << J_classe.back() -> get_XP() << endreq;
      break;
    case Jum:
      func() << "Perso à classes jumelées" << endreq;
      debug() << "Avant : " << J_classe.back() -> get_XP() << endreq;
      tmp_niv = J_classe.back() -> get_Niveau();
      a_distribuer = xp;
      J_classe.back() -> augmenter_xp(a_distribuer);
      if (tmp_niv != J_classe.back() -> get_Niveau())
	{
	  blank() << "Tu passes un niveau!" << endreq;
	  pv_gagnes = demander_unsigned("Entrer le nombre de PV obtenus");
	  ajouter_pv(pv_gagnes);
	  J_classe.back() -> augmenter_talents(0, true);
	}
      debug() << "Après : " << J_classe.back() -> get_XP() << endreq;
      break;
    default:
      error() << "TypeMulti inconnu dans Joueur::ajouter_xp" << endreq;
    }
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Permet la progression en PP du personnage
 *
 * FUNC  permet d'afficher le nombre de pp avant - après
 *
 *****************************************************************************/
void Joueur::ajouter_pp(const unsigned int& pp)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Avant : " << PP << endreq;
  PP += pp;
  func() << "Après : " << PP << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Permet la progression en PV du personnage
 *
 * FUNC  permet d'afficher le nombre de pv avant - après
 *
 *****************************************************************************/
void Joueur::ajouter_pv(const unsigned int& pv)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "Avant : " << PV << endreq;
  PV += pv;
  func() << "Après : " << PV << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Permet d'ajuster le nbr de PP à la création (Int)
 * 
 * FUNC permet d'afficher le changement
 *
 *****************************************************************************/
void Joueur::modificateur_PP()
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  func() << "PPs avant : " << PP << endreq;
  switch(J_classe[0] -> get_trait(3))
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
      PP += 1;
      break;
    case 9:
    case 10:
    case 11:
      PP += 2;
      break;
    case 12:
    case 13:
      PP += 3;
      break;
    case 14:
    case 15:
      PP += 4;
      break;
    case 16:
    case 17:
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
      PP += J_classe[0] -> get_trait(3) - 11;
      break;
    case 24:
      PP += 15;
      break;
    case 25:
      PP += 20;
      break;
    }
  func() << "PPs après : " << PP << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Permet d'ajuster le valeur d'une compétence non martiale
 * 
 * DEBUG permet d'afficher la valeur du trait correspondant
 * FUNC  permet d'afficher le changement
 *
 *****************************************************************************/

void Joueur::modificateur_val(unsigned int& val, const unsigned int& trait)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  debug() << "Trait numéo " << trait << endreq;
  func()  << "Valeur avant : " << val << endreq;
  switch(trait)
    {
    case 1:
    case 2:
    case 3:
      val -= 5;
      break;
    case 4:
      val -= 4;
      break;
    case 5:
      val -= 3;
      break;
    case 6:
      val -= 2;
      break;
    case 7:
      val -= 1;
      break;
    case 8:
    case 9:
    case 10:
    case 11:
    case 12:
    case 13:
      break;
    case 14:
      val += 1;
      break;
    case 15:
      val += 2;
      break;
    case 16:
      val += 3;
      break;
    case 17:
      val += 4;
      break;
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
    case 23:
    case 24:
    case 25:
      val += 5;
    }
  func()  << "Valeur après : " << val << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Retranscrit le nom sans espace ni apostrophes.
 *
 * INFO  
 * DEBUG 
 *
 *****************************************************************************/

string Joueur::convert_nom() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);

  string retour(Nom);
  unsigned int loc(retour.find("\\ "));

  while(loc != npos)
    {
      retour.replace(loc, 2, "");
      loc = retour.find("\\ ");
    }

  loc = retour.find("\\'");
  while(loc != npos)
    {
      retour.replace(loc, 2, "");
      loc = retour.find("\'");
    }

  func() << Nom << " -> " << retour << endreq;

  dout.setLevel(etat_precedent);

  return retour;
}

/******************************************************************************
 *
 * Enlève les doublons dans J_CompAccess
 *
 * INFO  
 * DEBUG 
 *
 *****************************************************************************/
void Joueur::nettoie_TC()
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(interne);
  vector<TypeClasse>::iterator it, loc, Begin(J_CompAccess.begin()),
    End(J_CompAccess.end());

  for (it = Begin; it != End; it++)
    {
      loc = find(it + 1, End, *it);
      if (loc != End)
	{
	  J_CompAccess.erase(loc);
	  End = J_CompAccess.end();
	  debug()  << "Valeur " << *it << " éffacée en "
		       << (unsigned int) (loc -Begin) << endreq;
	}
    }
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les traits et les ajustements correspondant.
 *
 * /!\ Grosse fonction ;-)
 *
 * INFO  : permet d'afficher le fichier que l'on édite
 *
 * DEBUG : permet d'afficher le score de Force (pr la gestion de For. Exc.)
 *
 *****************************************************************************/
void Joueur::ecrire_traits_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_tex);
  func() << "Joueur::ecrire_traits_tex() -> début" << endreq;
  /*
   * Alors le truc c'est ouvrir un chablon et lire les infos dedans
   * dans le chablon mettre un flag, genre '#' qui indique l'insertion d'une
   * donnée
   * ici on édite Feuilles/Nom/traits.inc.tex
   * Le chablon est dans Joueur0/
   */
  ifstream entree;
  ofstream sortie;
  string nom_fichier("Feuilles/"), ligne, str[33];
  bool for_ex(false);
  unsigned int i, exept(0), loc;
  for (i = 0; i < nb_classes; i++)
    {
      if (J_classe[i]->get_trait(0) == 18)
	{
	  if (J_classe[i] -> get_classe() == "Guerrier")
	    {
	      for_ex = true;
	      exept = J_classe[i]->get_trait(6);
	      break;
	    }
	  else if (J_classe[i] -> get_classe() == "Clerc")
	    {
	      unsigned int taille(J_classe[i] -> get_combien());
	      for (unsigned int j(0); j < taille; j++)
		{
		  if (J_classe[i] -> get_comp(j) == 38)
		    {
		      for_ex = true;
		      exept = J_classe[i]->get_trait(6);
		      break;
		    }
		}
	    }
	}
    }
  str[0] = Nom;
  loc = str[0].find("\\'");
  if (loc != npos)
    str[0].replace(loc, 2, "'");
  if (for_ex)
    str[1] = "$18^{" + write_int(exept) + "}$";
  else
    str[1] = "$" + write_int(J_classe[0]->get_trait(0)) + "$";

  debug() << "Force " << J_classe[0]->get_trait(0) << " -> " << str[1]  << endreq;

  for (i = 1; i < 6; i++)
    str[i+1] = "$" + write_int(J_classe[0]->get_trait(i)) + "$";

  for (i = 1; i < 7; i++)
    {
      if (str[i].size() < 4)
	str[i].replace(0, 1, "$\\phantom{0}");
    }

  unsigned int tmp_trait, tmp;
  if (!for_ex)
    {
      tmp = J_classe[0]->get_trait(0) - 1;
    }
  else
    {
      tmp_trait = J_classe[0]->get_trait(6);
      if (tmp_trait <= 50)
	tmp = 25;
      else if (tmp_trait <= 75)
	tmp = 26;
      else if (tmp_trait <= 90)
	tmp = 27;
      else if (tmp_trait <= 99)
	tmp = 28;
      else
	tmp = 29;
    }
  for (i = 0; i < 6; i++)
    str[7+i] = Aj_Force[tmp][i];

  tmp_trait = J_classe[0]->get_trait(1);

  if (tmp_trait < 7)
    tmp = tmp_trait -1;
  else if (tmp_trait < 15)
    tmp = 6;
  else if (tmp_trait < 19)
    tmp = tmp_trait - 8;
  else if (tmp_trait < 21)
    tmp = 11;
  else if (tmp_trait < 24)
    tmp = 12;
  else
    tmp = 13;
  for (i = 0; i < 3; i++)
    str[13+i] = Aj_Dexterite[tmp][i];

  tmp = J_classe[0]->get_trait(2) - 1;
  for (i = 0; i < 5; i++)
    str[16+i] = Aj_Const[tmp][i];

  tmp_trait = J_classe[0]->get_trait(3);
  if (tmp_trait < 2)
    tmp = tmp_trait - 1;
  else if (tmp_trait < 9)
    tmp = 1;
  else
    tmp = tmp_trait - 7;

  for (i = 0; i < 5; i++)
    str[21+i] = Aj_Int[tmp][i];
  
  tmp_trait = J_classe[0]->get_trait(4);
  if (tmp_trait < 14)
    tmp = tmp_trait - 1;
  else
    tmp = tmp_trait - 2;

  for (i = 0; i < 4; i++)
    str[26+i] = Aj_Sagesse[tmp][i];

  tmp_trait = J_classe[0]->get_trait(5);
  if (tmp_trait < 10)
    tmp = tmp_trait - 1;
  else if (tmp_trait < 13)
    tmp = 8;
  else
    tmp = tmp_trait - 3;
  for (i = 0; i < 3; i++)
    str[30+i] = Aj_Charisme[tmp][i];
      

  entree.open("Joueur0/traits0.inc.tex");


  nom_fichier += convert_nom();
  nom_fichier += "/traits.inc.tex";
  info() << "Ecriture de " << nom_fichier << endreq;
  sortie.open(nom_fichier.c_str());
  debug() << "Etat ouverture fichier " << sortie.fail() << endreq;

  i = 0;
  while(!entree.eof())
    {
      getline(entree, ligne);
      if (ligne[0] != '#')
	sortie << ligne << endl;
      else
	{
	  debug() << i << " -> " << str[i] << endreq;
	  sortie << str[i];
	  i++;
	}
    }
  entree.close();
  sortie.close();
  func() << "Joueur::ecrire_traits_tex -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit la table des JS du Joueur.
 * Gère les classes multiples en prenant le JS le plus bas.
 *
 * INFO  permet d'afficher le fichier que l'on édite
 *
 * LFUNC permet d'afficher les différents JS, dans l'ordre, de chaque Classe
 *       ainsi que les JS finaux
 * 
 *****************************************************************************/
void Joueur::ecrire_JS_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_tex);
  func() << "Joueur::ecrire_JS_tex -> début" << endreq;
  /*
   * Alors le truc c'est ouvrir un chablon et lire les infos dedans
   * dans le chablon mettre un flag, genre '#' qui indique l'insertion d'une
   * donnée
   * ici on édite Feuilles/Nom/JS.inc.tex
   * Le chablon est dans Joueur0/
   */
  ifstream entree;
  ofstream sortie;
  string nom_fichier("Feuilles/"), ligne, str[5];
  unsigned int JS[5] = {20, 20, 20, 20, 20}, tmp_JS[5], *ptr(tmp_JS);
  unsigned int i, combien, bonus(0);

  for (i = 0; i < nb_classes; i++)
    {
      J_classe[i] -> get_JS(ptr);
      for (unsigned int j(0); j < 5; j++)
	{
	  lfunc() << "JS[" << i << ',' << j << "] "<<tmp_JS[j] << endreq;
	  if (tmp_JS[j] < JS[j])
	    JS[j] = *(tmp_JS + j);
	}
    }

  /*
   * On traite ici les races qui peuvent avoir un bonus aux JS
   */
  string race;
  bool poison(false), a_bonus(false);
  race = J_race -> get_Type();
  combien = J_race -> get_taille();

  debug() << "race = " << race << endreq;

  for(i = 0; i < combien; i++)
    {
      if (race == "Gnome" && J_race -> get_capa(i) == 3)
	{
	  func() << "Joueur::ecrire_JS_tex -> bonus aux JS de gnome" << endreq;
	  a_bonus = true;
	  break;
	}
      else if (race == "Hobbit" && J_race -> get_capa(i) == 2)
	{
	  func() << "Joueur::ecrire_JS_tex -> bonus aux JS de hobbit" << endreq;
	  a_bonus = true;
	  poison = true;
	  break;
	}
      else if (race == "Nain" && J_race -> get_capa(i) == 1)
	{
	  func() << "Joueur::ecrire_JS_tex -> bonus aux JS de nain" << endreq;
	  a_bonus = true;
	  poison = true;
	  break;
	}
    }

  if (a_bonus)
    {
      switch(J_classe[0] -> get_trait(2))
	{
	case 4:
	case 5:
	case 6:
	  bonus = 1;
	  break;
	case 7:
	case 8:
	case 9:
	case 10:
	  bonus = 2;
	  break;
	case 11:
	case 12:
	case 13:
	  bonus = 3;
	  break;
	case 14:
	case 15:
	case 16:
	case 17:
	  bonus = 4;
	  break;
	case 18:
	case 19:
	case 20:
	  bonus = 5;
	  break;
	default:
	  bonus = 0;
	}
      JS[1] -= bonus;
      JS[4] -= bonus;
    }

  for (i = 0; i < 5; i++)
    {
      if (i == 0 && poison)
	str[i] = "$" + write_int(JS[i]) + " (" + write_int(JS[i] - bonus) + ")$";
      else
	str[i] = "$" + write_int(JS[i]) + "$";
    }

  entree.open("Joueur0/JS0.inc.tex");


  nom_fichier += convert_nom();
  nom_fichier += "/JS.inc.tex";
  info() << "Ecriture de " << nom_fichier << endreq;
  sortie.open(nom_fichier.c_str());

  i = 0;
  while(!entree.eof())
    {
      getline(entree, ligne);
      if (ligne[0] != '#')
	sortie << ligne << endl;
      else
	{
	  linfo() << i << " -> " << str[i] << endreq;
	  sortie << str[i];
	  i++;
	}
    }
  sortie.close();
  entree.close();
  func() << "Joueur::ecrire_JS_tex -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit le nbr de PV, le TAc0 et la CA
 *
 * INFO  permet d'afficher le fichier que l'on édite
 *
 * DEBUG permet d'afficher ces trois nombres
 *
 *****************************************************************************/
void Joueur::ecrire_scores_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_tex);
  func() << "Joueur::ecrire_scores_tex -> début" << endreq;
  ifstream entree;
  ofstream sortie;
  string nom_fichier("Feuilles/"), ligne, str[6];
  unsigned int i;

  str[0] = "$"+write_int(PV)+"$";
  str[1] = "$"+write_int(TAc0)+"$";
  str[2] = "$"+write_int(CA)+"$";
  str[3] = "$"+write_int(PP)+"$";
  str[4] = "$"+write_int(J_classe.back() -> get_XP())+"$";
  debug() << "XP : " << J_classe.back() -> get_XP()
	      << " -> " << write_int(J_classe.back() -> get_XP()) << endreq;
  switch(TM_switch)
    {
    case Mul:
      str[5] = "$"+write_int(nb_classes * J_classe.back() -> get_XP())+"$";
      break;
    case Jum:
      unsigned int total;
      for (i = 0; i < nb_classes; i++)
	total += J_classe[i] -> get_XP();
      str[5] = "$"+write_int(total)+"$";
      break;
    case Non:
      str[5] = str[4];
      break;
    }

  entree.open("Joueur0/scores0.inc.tex");

  nom_fichier += convert_nom();
  nom_fichier += "/scores.inc.tex";
  info() << "Ecriture de " << nom_fichier << endreq;
  sortie.open(nom_fichier.c_str());

  i = 0;
  while(!entree.eof())
    {
      getline(entree, ligne);
      if (ligne[0] != '#')
	sortie << ligne << endl;
      else
	{
	  debug() << i << " -> " << str[i] << endreq;
	  sortie << str[i];
	  i++;
	}
    }
  sortie.close();
  entree.close();
  func() << "Joueur::ecrire_scores_tex -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit la Race et les capacités raciales
 *
 * INFO  permet d'affiche le fichier que l'on édite
 *
 * FUNC  permet d'afficher le nombre de capacités raciales
 *
 * DEBUG permet d'afficher ces capacités
 *
 *****************************************************************************/
void Joueur::ecrire_race_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_tex);
  func() << "Joueur::ecrire_race_tex -> début" << endreq;
  ofstream sortie;
  string nom_fichier("Feuilles/");

  unsigned int taille(J_race->get_taille());
  vector<string> str;
  str.push_back("\\subsection*{"+J_race->get_Type()+"}");
  func() << "Nbr capa : " << taille << endreq;

  for (unsigned int i(0); i < taille; i++)
    {
      str.push_back(J_race->get_capacite(i));
      lfunc() << str[i+1] << endreq;
    }

  nom_fichier += convert_nom();
  nom_fichier += "/race.inc.tex";
  info() << "Ecriture de " << nom_fichier << endreq;
  sortie.open(nom_fichier.c_str());

  sortie << str[0] << endl;
  sortie << "\\begin{itemize}" << endl;
  for (unsigned int i(0); i < taille; i++)
    sortie << "\\item [-] " << str[i+1] << endl;
  if (taille == 0)
    sortie << "\\item [] Aucune" << endl;
  sortie << "\\end{itemize}" << endl;
  
  sortie.close();
  func() << "Joueur::ecrire_race_tex -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit la Classe et les compétences de Classe
 *
 * INFO  permet d'afficher le fichier que l'on édite
 *
 * LINFO permet d'afficher le nombre de compétences, et si elle est
 * associée à un pourcentage
 *
 * LFUNC permet de savoir lesquelles on "saute"
 *
 * DEBUG permet de toutes les afficher
 *
 *****************************************************************************/
void Joueur::ecrire_classe_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_tex);
  func() << "Joueur::ecrire_classe_tex -> début" << endreq;
  ofstream sortie;
  string nom_fichier("Feuilles/"), tmp;
  vector<string> str;
  bool override(false);

  nom_fichier += convert_nom();
  nom_fichier += "/classe.inc.tex";
  info() << "Ecriture de " << nom_fichier << endreq;
  sortie.open(nom_fichier.c_str());

  for (unsigned int i(0); i < nb_classes; i++)
    {
      str.clear();
      unsigned int taille(J_classe[i]->get_combien());
      str.push_back("\\subsection*{"+J_classe[i]->get_classe()+" (niveau $"+write_int(J_classe[i]->get_Niveau())+"$)}");
      linfo() << "Nbr comp : " << taille << endreq;

      for (unsigned int j(0); j < taille; j++)
	{
	  if (override)
	    {
	      override = false;
	      debug() << "On saute celui-là" << endreq;
	      continue;
	    }
	  debug() << "ici j = " << j << endreq;
	  tmp = J_classe[i]->get_competence(j);
	  debug() << tmp << endreq;
	  if ((char)tmp[0] == ' ')
	    {
	      lfunc() << "Pourcentage, attention!" << endreq;
	      str.push_back(tmp);
	      override = true;
	    }
	  else
	    str.push_back(tmp);
	}
      sortie << str[0] << endl;
      sortie << "\\begin{itemize}" << endl;
      taille = str.size();
      for (unsigned int j(1); j < taille; j++)
	sortie << "\\item [-] " << str[j] <<endl;
      sortie << "\\end{itemize}" << endl;
    }
  sortie.close();
  func() << "Joueur::ecrire_classe_tex -> début" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les désavantages, dons et compétences non martiales
 *
 * INFO  permet d'afficher le fichier que l'on édite
 *
 * FUNC  permet d'afficher le nombre de compétences, et si elle est
 *       associée à un pourcentage
 *
 * DEBUG permet de toutes les afficher, de savoir lesquelles on "saute",
 *       ie celles qui ont un pourcentage associé.
 *
 *****************************************************************************/
void Joueur::ecrire_comp_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_tex);
  func() << "Joueur::ecrire_comp_tex -> début" << endreq;
  ofstream sortie;
  string nom_fichier("Feuilles/"), tmp;
  vector<string> str;

  nom_fichier += convert_nom();
  nom_fichier += "/comp.inc.tex";
  info() << "Ecriture de " << nom_fichier << endreq;
  sortie.open(nom_fichier.c_str());

  unsigned int nbr, i;

  // On s'occupe des désavantages

  nbr = get_combien_desavantages();

  if (nbr > 0)
    sortie << "\\subsection*{Désavantages}" << endl << "\\begin{itemize}"
	   << endl;

  for (i = 0; i < nbr; i++)
    {
      sortie << "\\item [-] " << Desavantages[J_Desavantages[i]].Capa << endl;
    }

  if (nbr > 0)
    sortie << "\\end{itemize}" << endl;

  // On s'occupe ensuite des dons

  nbr = get_combien_dons();

  if (nbr > 0)
    sortie << "\\subsection*{Dons}" << endl << "\\begin{itemize}" << endl;

  for (i = 0; i < nbr; i++)
    {
      sortie << "\\item [-] " << Dons[J_Dons[i]].Capa << endl;
    }

  if (nbr > 0)
    sortie << "\\end{itemize}" << endl;

  // On s'occupe ensuite des compétences diverses

  nbr = get_combien_competences();

  if (nbr > 0)
    sortie << "\\subsection*{Compétences diverses}" << endl
	   << "\\begin{itemize}" << endl;

  for (i = 0; i < nbr; i+=2)
    {
      sortie << "\\item [-] "
	     << "\\begin{tabular*}{12cm}{@{\\extracolsep{\\fill}}l r}"
	     << endl << CompetencesDiverses[J_CompDiv[i]].Comp << " & "
	     << J_CompDiv[i+1] << endl << "\\end{tabular*}" << endl;
    }

  if (nbr > 0)
    sortie << "\\end{itemize}" << endl;

  // On passe aux compétences martiales

  nbr = get_combien_comp_martiales();

  if (nbr > 0)
    sortie << "\\subsection*{Compétences martiales}" << endl
	   << "\\begin{footnotesize}" << endl
	   << "\\begin{tabular*}{14cm}{@{\\extracolsep{\\fill}} l l l l l l l l l}"
	   << endl << "Arme & Poids & Taille & Type & Init. & Tir & Portée & Dégâts PM & Dégâts G \\\\"
	   << endl;

  unsigned int j(0);
  
  for (i = 0; i < nbr; i++)
    {
      j = J_Martiales[i];
 
      do
	{
	  sortie << Toutes_armes[j].Nom_arme << " & "
		 << Toutes_armes[j].poids << " & "
		 << Toutes_armes[j].taille_arme << " & "
		 << Toutes_armes[j].type_degats << " & "
		 << Toutes_armes[j].Vitesse << " & "
		 << Toutes_armes[j].Frequence << " & "
		 << Toutes_armes[j].Portee << " & "
		 << Toutes_armes[j].degats_PM << " & "
		 << Toutes_armes[j].degats_G << "\\\\"
		 << endl;
	  j++;
	}
      while (Toutes_armes[j-1].afficher_suite);

    }

  if (nbr > 0)
    sortie << "\\end{tabular*}" << endl << "\\end{footnotesize}" << endl;

  sortie.close();
  func() << "Joueur::ecrire_comp_tex -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les sorts du Livre de Sorts (pour un mage, barde) ou les sorts
 * des sphères accessibles (clerc, druide, rôdeur, paladin).
 *
 * Pour un Joueur à Classe multiple, le .tex contient les informations des
 * deux classes concaténées.
 *
 * INFO  permer d'afficher le fichier que l'on édite
 *
 * DEBUG permet d'afficher la classe courante
 *
 *****************************************************************************/
void Joueur::ecrire_sorts_tex() const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_tex);
  func() << "Joueur::ecrire_sorts_tex -> début" << endreq;
  string nom_fichier;
  bool ecraser;
  for (unsigned int i(0); i < nb_classes; i++)
    {
      ecraser = (i == 0);
      nom_fichier = "Feuilles/" + convert_nom() + "/sorts.inc.tex";
      //fichier = "sorts.inc.tex";
      info() << "Ecriture de " << nom_fichier << endreq;
      debug() << J_classe[i] -> get_classe() << endreq;
      J_classe[i] -> ecrire_sorts(nom_fichier, ecraser);
    }
  func() << "Joueur::ecrire_sorts_tex -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Méthodes XML
 *
 *****************************************************************************/

void Joueur::trouver_o(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  int ret(-1); 
  /*
   * La valeur -1 est assignee au cas ou on ne rencontre plus de <
   */
  for(unsigned int i(index);i<a.size();i++)
    /*
     * On commence avec la valeur donnee par l'index, derniere position
     * lue par l'index
     */
    {
      if(a[i]=='<')
	{
	  ret=i;
	  index=i+1; 
	  /*
	   * On met a jour l'index de lecture ssi elle trouve un <
	   */
	  break;
	}
    }
  /* 
   * Si la methode ne trouve plus de < elle ne met pas a jour l index de
   * lecture
   */
  if(ret==-1) //erreur
    {
      error() << "Début de balise non trouvée, Joueur::trouver_o" << endreq;
      exit(1);
    }
  dout.setLevel(etat_precedent);
}

void Joueur::trouver_f (string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  int ret(-1); 
  /*
   * La valeur -1 est assignee au cas ou on ne rencontre plus de /
   */
  for(unsigned int i(index);i<a.size();i++)
 /*
  * On commence avec la valeur donnee par l'index, derniere position lue
  * par l'index
  */
    {
      if(a[i]=='>')
	{
	  ret=i;
	  index++;
	  /*
	   * On met a jour l'index de lecture
	   */
	  break;
	}
    }
  if(ret==-1) //erreur
    {
      error() << "Fin de balise non trouvée dans Joueur::trouver_f" << endreq;
      exit(1);
    }
  dout.setLevel(etat_precedent);
}

int Joueur::trouver_o_I (string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  int ret(-1);
  /*
   * La valeur -1 est assignee au cas ou on ne rencontre plus de <
   */
  for(unsigned int i(index);i<a.size();i++)
    /*
     * On commence avec la valeur donnee par l'index, derniere position
     * lue par l'index
     */
    {
      if(a[i]=='<')
	{
	  ret=i;
	  index++; //on met a jour l'index de lecture ssi elle trouve un <
	  break;
	}
    }
  /*
   * Si la methode ne trouve plus de < elle ne met pas a jour l'index
   * de lecture
   */
  dout.setLevel(etat_precedent);
  return ret;
}

int Joueur::trouver_f_I (string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  int ret(-1);
  /*
   * La valeur -1 est assignee au cas ou on ne rencontre plus de /
   */

  for(unsigned int i(index);i<a.size();i++)
    /*
     * On commence avec la valeur donnee par l'index, derniere position
     * lue par l'index
     */
    {
      if(a[i]=='>')
	{
	  ret=i;
	  index++; //on met a jour l'index de lecture
	  break;
	}
    }
  dout.setLevel(etat_precedent);
  return ret;
}

/******************************************************************************
 *
 * Permet de s'affranchir des ' ' entre deux balises, deux informations, ...
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::sauter_blanc(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  func() << "sauter_blanc -> début" << endreq;
  while ( (a[index]==32) || (a[index]==10))
    {
      index++;
    }
  func() << "sauter_blanc -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Fait disparaître les ' ' à la fin d'une string lors de la récupération
 * depuis un fichier .xml
 *
 *****************************************************************************/
void Joueur::wipe_blank(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  unsigned int i(a.size());
  while (a[i] != ' ')
    i--;
  string tmp("");
  for (unsigned int j(0); j < i; j++)
    tmp += a[j];
  a = tmp;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
string Joueur::lit_balise(string& a ,char& b)
  /*
   * Ici l'attribut b defini si c'est une balise ouvrante ou fermante
   */
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  func() << "lit_balise -> début" << endreq;
  if(a[index]=='/') 
    /*
     * On a affaire a une balise fermante
     */
    {
      index+=1;
      b='f';
      /*
       * On oublie pas d avancer l index
       * C'est une fermante
       */
    }
  else 
    {
      b='o';
      /*
       * C'est une ouvrante
       */
    }
  
  string out("");
  while(a[index]!='>')
    {
      out+=a[index];
      index++;
    }
  func() << "lit_balise -> fin" << endreq;
  dout.setLevel(etat_precedent);
  return out;
}

/******************************************************************************
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::skip_comment(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  func() << "skip_comment -> début" << endreq;
  int ancienne_pos_index(index);
  /*
   * Memorise la position initiale de l'index
   */
  int temp(trouver_o_I(a));
  /*
   * La position de l index est modifiee ici
   */
  if (temp==-1) index=ancienne_pos_index;
  /*
   * Plus de commentaire possible cas pas de <
   */
  else
    /*
     * Il a trouve un <
     */
    {
      sauter_blanc(a);
      /*
       * Il saute les blancs et pointe le premier caractere apres <
       */
      if(a[index]=='!')
	/*
	 * On a affaire a un commentaire car commence par !
	 */
	{
	  int blabla(trouver_f_I(a));
	  /*
	   * Cherche la fin du commentaire (il cherche >) et met à jour
	   l'index de lecture, job terminé
	  */
	  if(blabla==-1)
	    /*
	     * Cas ou le commentaire n a pas de fin -> Erreur !
	     */
	    {
	      error() << "Syntaxe de commentaire incorrecte dans Joueur::skip_comment()" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  /*
	   * Si le caractère n'est pas '!' il remet l'index ou il était,
	   * il n a pas eu affaire à un commentaire
	   */
	  index=ancienne_pos_index;
	}
    }
  func() << "skip_comment -> fin" << endreq;
  /*
   * Au final la position de l'index est modifiée que si un commentaire
   * a été trouvé et dans un tel cas on a "passé" le commentaire
   */
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Gestion de la bonne structure du fichier .xml
 * Cherche le contenu de la balise suivante et le compare à la string b
 *
 *****************************************************************************/
bool Joueur::verifier_contenu_futur(string& a, string& b)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  char o_f('o');
  int mem_pos(index);
  skip_comment(a);
  trouver_o(a);
  string c(lit_balise(a,o_f));
  index=mem_pos;
  dout.setLevel(etat_precedent);
  if ((c==b) && (o_f=='f')) return true;
  else return false;
}

/******************************************************************************
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
int Joueur::read_int(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_elementaire_xml);
  func() << "read_int -> début" << endreq;
  while(!c_un_chiffre(a[index])) index++;
  /*
   * Le signe est traite
   * int pos_virgule(0); //position de la virgule
   */
  vector<int> tab;
  for(unsigned int i(index);i<a.size();i++)
    {
      if(c_un_chiffre(a[i]))
	{
	  tab.push_back(translate(a[i]));
	  index+=1;
	}
      else break;
      /*
       * si on lit plus de chiffre ou alors de virgule on quitte
       */
    }
  /*
   * Le tableau est maintenant correctement rempli
   */
  int ret(0);
  for(unsigned int h(0);h<tab.size();h++)
    {
      unsigned int puissance_10(tab.size()-h-1);
      int ajout((tab[h]*puissance(10,puissance_10)));
      ret+=ajout;
    }
  func() << "read_int -> fin" << endreq;
  dout.setLevel(etat_precedent);
  return ret;
}

/******************************************************************************
 *
 * Traduit un 'char' en un 'int'
 *
 *****************************************************************************/
int Joueur::translate(char a)
{
  func() << a << endreq;
  if (a=='0') return 0;
  if (a=='1') return 1;
  if (a=='2') return 2;
  if (a=='3') return 3;
  if (a=='4') return 4;
  if (a=='5') return 5;
  if (a=='6') return 6;
  if (a=='7') return 7;
  if (a=='8') return 8;
  if (a=='9') return 9;
  else
    {
      error() << "Traduction d'un caractere en chiffre impossible dans Joueur::translate" << endreq;
      exit(1);
    }
}


/******************************************************************************
 *
 * Vérifie que le caractère lu représente bien un chiffre
 *
 *****************************************************************************/
bool Joueur::c_un_chiffre(char b)
{
  switch(b)
    {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      return true;
    default:
      return false;
    }
}

/**************************************************************************//**
 *
 * Gestion des sous-modules de récupération des données depuis le .xml
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_joueur(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire joueur -> début" << endreq;
  skip_comment(a);
  sauter_blanc(a);
  unsigned int tabl[7];
  char ouvrante_fermante;
  trouver_o(a);
  string  contenu_balise(lit_balise(a, ouvrante_fermante));
  if(ouvrante_fermante=='o')
    // On vérifie que c'est une balise ouvrante et qu'elle existe
    {
      if (contenu_balise=="Joueur")
	{
	  skip_comment(a);
	  Nom = trouver_interpreter_ecrire_nom(a);
	  skip_comment(a);
	  sauter_blanc(a);
	  trouver_interpreter_ecrire_typeRace(a);
	  skip_comment(a);
	  trouver_interpreter_ecrire_traits(a, tabl);
	  skip_comment(a);
	  trouver_interpreter_ecrire_typeClasse(a, tabl);
	  contenu_balise==lit_balise(a,ouvrante_fermante);
	  // On ecrit le contenu de la balise
	  // Cherche fin de la balise ouvrante s'il trouve > alors c'est ok
	  // et il a mis a jour l'attribut 'index' de la classe
	  trouver_interpreter_ecrire_dons(a, J_Dons);
	  trouver_interpreter_ecrire_desavantages(a, J_Desavantages);
	  trouver_interpreter_ecrire_nonmart(a, J_CompDiv);
	  trouver_interpreter_ecrire_martiales(a, J_Martiales);
	}
      else
	// Le contenu de la balise ne correspond pas a la syntaxe autorisee
	{
	  error() << "Syntaxe erronée du Joueur dans Joueur::trouver_interpreter_ecrire_joueur" << endreq;
	  exit(1);
	}
      {
	// Dans ce cas rien a dire on est ok
      }
    }
  else 
    // Cas ou la balise ouvrante est en fait fermante
    {
      error() << "Balise ouvrante de Joueur incorrecte dans Joueur::trouver_interpreter_ecrire_joueur" << endreq;
      exit(1);
    }
  func() << "Ecrire joueur -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Lit la Race, ie la string qui la caractérise, ainsi que les différentes
 * capacités raiciales.
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_typeRace(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire typeRace -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise=="Info_Raciales")
	{
	  skip_comment(a);
	  string race(trouver_interpreter_ecrire_race(a));
	  vector<unsigned int> capa;
	  skip_comment(a);
	  trouver_interpreter_ecrire_capacites(a, capa);
	  sauter_blanc(a);
	  if (race == "Humain")
	    J_race = new Humain(capa);
	  else if (race == "Nain")
	    J_race = new Nain(capa);
	  else if (race == "Elfe")
	    J_race = new Elfe(capa);
	  else if (race == "Gnome")
	    J_race = new Gnome(capa);
	  else if (race == "Hobbit")
	    J_race = new Hobbit(capa);
	  else if (race == "Demi-Elfe")
	    J_race = new DemiElfe(capa);
	  else if (race == "Demi-Orque")
	    J_race = new DemiOrque(capa);
	  else if (race == "Demi-Ogre")
	    J_race = new DemiOgre(capa);
	  else
	    {
	      error() << "Race inconnue (" << race << ')' << endreq;
	      exit(1);
	    }
	  trouver_f(a); //cherche fin de la balise ouvrante
	  //s il trouve > alors c ok et il a mis a jour l attribut index de la classe
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	}
      else //le contenu de la balise ne correspond pas a la syntaxe autorisee
	{
	  error() << "Syntaxe erronée des infos raciales dans Joueur::trouver_interpreter_ecrire_typeRace" << endreq;
	  exit(1);
	}
    }
  func() << "Ecrire typeRace -> fin (" << contenu_balise << ')' << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Lit la Classe, ie la string qui la caractérise, ainsi que les différentes
 * compétences
 *
 * FUNC  permet d'afficher le nombre de compétences et les messages de début
 *       et de fin
 *
 * DEBUG permet d'afficher le contenu de la dernière balise
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_typeClasse(string& a,unsigned int tab[7] )
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire typeClasse -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise, classe;
  unsigned int xp;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise=="Info_Classe")
	{
	  trouver_f(a); //cherche fin de la balise ouvrante
	  //s il trouve > alors c ok et il a mis a jour l attribut index de la classe
	  skip_comment(a);
	  nb_classes = trouver_interpreter_ecrire_nb(a);
	  if (nb_classes == 1)
	    TM_switch = Non;
	  else
	    {
	      if (J_race -> get_Type() == "Humain")
		TM_switch = Jum;
	      else
		TM_switch = Mul;
	    }
	  PV = trouver_interpreter_ecrire_PV(a);
	  PP = trouver_interpreter_ecrire_PP(a);
	  // ajouter lecture TypeClasse J_CompAccess
	  trouver_interpreter_ecrire_access(a);
	  vector<unsigned int> comp;
	  vector<Sort> tmp_sort;
	  
	  /*
	   * Traitements des classes proprement dites
	   */
	  for (unsigned int i(0); i < nb_classes; i++)
	    {
	      classe = trouver_interpreter_ecrire_classe(a);
	      xp = trouver_interpreter_ecrire_XP(a);
	      trouver_interpreter_ecrire_competences(a, comp);
	      
	      func() << "nbr de compétences " << comp.size() << endreq;

	      if (classe == "Barde")
		J_classe.push_back(new Barde(xp, tab));
	      else if (classe == "Clerc")
		J_classe.push_back(new Clerc(xp, tab));
	      else if (classe == "Druide")
		J_classe.push_back(new Druide(xp, tab));
	      else if (classe == "Guerrier")
		J_classe.push_back(new Guerrier(xp, tab));
	      else if (classe == "Mage")
		J_classe.push_back(new Mage(xp, tab));
	      else if (classe == "Paladin")
		J_classe.push_back(new Paladin(xp, tab));
	      else if (classe == "Rodeur")
		J_classe.push_back(new Rodeur(xp, tab));
	      else if (classe == "Spécialiste")
		J_classe.push_back(new Spec(xp, tab));
	      else if (classe == "Voleur")
		J_classe.push_back(new Voleur(xp, tab));
	      J_classe.back() -> set_Competences(comp);
	      comp.clear();

	      trouver_interpreter_ecrire_sorts(a, tmp_sort);
	      J_classe.back() -> set_Sorts(tmp_sort);
	      tmp_sort.clear();
	      J_classe.back() -> calcul_niveau();
	      J_classe.back() -> calcul_niv_mag();
	    }
	  trouver_f(a); //cherche fin de la balise ouvrante
	  //s il trouve > alors c ok et il a mis a jour l attribut index de la classe
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	}
      else //le contenu de la balise ne correspond pas a la syntaxe autorisee
	{
	  error() << "Syntaxe erronée des infos de classe dans Joueur::trouver_interpreter_ecrire_typeClasse" << endreq;
	  exit(1);
	}
    }
  func() << "Ecrire typeClasse -> fin" << endreq;
  debug() << contenu_balise << " " << ouvrante_fermante << endreq << flush;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Ecrit le Nom du Joueur
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
string Joueur::trouver_interpreter_ecrire_nom(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire nom -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  string retour;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Nom")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      retour+=a[index];
	      index++;
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Nom")
		{
		  func() << "Ecrire nom -> fin" << endreq;
		  wipe_blank(retour);
		  // On enlève les blancs inutiles à la fin ;-)
		  dout.setLevel(etat_precedent);
		  return retour;
		}
	      else
		{
		  error() << "Balise supposée être </Nom> dans Joueur::trouver_interpreter_ecrire_nom" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans  Joueur::trouver_interpreter_ecrire_nom" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Nom> dans Joueur::trouver_interpreter_ecrire_nom" << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_nom" << endreq;
      exit(1);;
    }
}

/******************************************************************************
 *
 * Ecrit le 'type' de Race, ie le nom de la Race
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
string Joueur::trouver_interpreter_ecrire_race(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire race (str) -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  string retour;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Race")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      retour+=a[index];
	      index++;
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Race")
		{
		  func() << "Ecrire race (str) -> fin" << endreq;
		  wipe_blank(retour);
		  dout.setLevel(etat_precedent);
		  return retour;
		}
	      else
		{
		  error() << "Balise supposée être </Race> dans Joueur::trouver_interpreter_ecrire_race" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans  Joueur::trouver_interpreter_ecrire_race" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Race> dans Joueur::trouver_interpreter_ecrire_race" << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_race (" << contenu_balise << ") " << ouvrante_fermante << endreq;
      exit(1);;
    }
}

/******************************************************************************
 *
 * Ecrit le 'type' de Classe, ie le nom de la Classe
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
string Joueur::trouver_interpreter_ecrire_classe(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire classe -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  string retour;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Classe")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      retour+=a[index];
	      index++;
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Classe")
		{
		  func() << "Ecrire classe -> fin" << endreq;
		  wipe_blank(retour);
		  dout.setLevel(etat_precedent);
		  return retour;
		}
	      else
		{
		  error() << "Balise supposée être </Classe> dans Joueur::trouver_interpreter_ecrire_classe" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans  Joueur::trouver_interpreter_ecrire_classe" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Classe> dans Joueur::trouver_interpreter_ecrire_classe" << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_classe" << endreq;
      exit(1);;
    }
}

/**************************************************************************//**
 *
 * Ecrit les capacités raciales dans le tableau 'cap'
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 * LFUNC permet d'afficher un message d'état de lecture (=> comptage)
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_capacites(string& a, vector<unsigned int>& cap)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire capacites -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Capacites")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      cap.push_back(read_int(a));
	      sauter_blanc(a);
	      lfunc() << "Capacité lue" << endreq;
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Capacites")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Capacites> dans Joueur::trouver_interpreter_ecrire_capacites" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_capacites" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Capacites> dans Joueur::trouver_interpreter_ecrire_capacites" << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_capacites" << endreq;
      exit(1);;
    }
  func() << "Ecrire capacites -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit dans 'tab' les 6 trait plus le pseudo-trait qui gère la Force
 * Exceptionelle
 *
 * FUNC  permet d'afficher les messages de début et de fin
 * LFUNC permet d'afficher les traits
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_traits(string& a, unsigned int tab[7])
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire Traits -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Traits")
	{
	  sauter_blanc(a);
	  for (unsigned int i(0); i < 7; i++)
	    {
	      lfunc() << "Trait " << i << " lu" << endreq;
	      tab[i] = read_int(a);
	      sauter_blanc(a);
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Traits")
		{
		  func() << "Ecrire Traits -> fin" << endreq;
		}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Traits> dans Joueur::trouver_interpreter_ecrire_traits (" << contenu_balise << " ) " << ouvrante_fermante << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_traits" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Traits> dans Joueur::trouver_interpreter_ecrire_traits" << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_traits (" << contenu_balise << ") " << ouvrante_fermante << endreq;
      exit(1);;
    }
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les compétences de classe dans le tableau 'cap'
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_competences(string& a, vector<unsigned int>& cap)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire competences -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Competences")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      cap.push_back(read_int(a));
	      sauter_blanc(a);
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Competences")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Competences> dans Joueur::trouver_interpreter_ecrire_competences" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_competences" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Competences> dans Joueur::trouver_interpreter_ecrire_competences (" << contenu_balise << ") " << ouvrante_fermante << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_competences" << endreq;
      exit(1);
    }
  if (!cap.empty())
    func() << "Dernière competence " << cap.back() << endreq;
  func() << "Ecrire competences -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les dons de classe dans le tableau 'cap'
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_dons(string& a, vector<unsigned int>& cap)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire dons -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Dons")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      cap.push_back(read_int(a));
	      sauter_blanc(a);
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Dons")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Don> dans Joueur::trouver_interpreter_ecrire_dons" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_dons" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Don> dans Joueur::trouver_interpreter_ecrire_dons (" << contenu_balise << ") " << ouvrante_fermante << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_dons (" << contenu_balise << ") " << ouvrante_fermante << endreq;
      exit(1);
    }
  if (!cap.empty())
    func() << "Dernier don " << cap.back() << endreq;
  func() << "Ecrire dons -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les desavantages de classe dans le tableau 'cap'
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_desavantages(string& a, vector<unsigned int>& cap)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire desavantages -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Desavantages")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      cap.push_back(read_int(a));
	      sauter_blanc(a);
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Desavantages")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Desavantages> dans Joueur::trouver_interpreter_ecrire_desavantages" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_desavantages" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Desavantages> dans Joueur::trouver_interpreter_ecrire_desavantages (" << contenu_balise << ") " << ouvrante_fermante << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_desavantages" << endreq;
      exit(1);
    }
  if (!cap.empty())
    func() << "Dernier désavantage " << cap.back() << endreq;
  func() << "Ecrire desavantages -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les compétences non martiales de classe dans le tableau 'cap'
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_nonmart(string& a, vector<unsigned int>& cap)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire nonmart -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Non-martiales")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      cap.push_back(read_int(a));
	      sauter_blanc(a);
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Non-martiales")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Non-martiales> dans Joueur::trouver_interpreter_ecrire_nonmart" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_nonmart" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Non-martiales> dans Joueur::trouver_interpreter_ecrire_nonmart (" << contenu_balise << ") " << ouvrante_fermante << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_nonmart" << endreq;
      exit(1);
    }
  func() << "Ecrire nonmart -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les compétences martiales de classe dans le tableau 'cap'
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_martiales(string& a, vector<unsigned int>& cap)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire martiales -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Martiales")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      cap.push_back(read_int(a));
	      sauter_blanc(a);
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Martiales")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Martiales> dans Joueur::trouver_interpreter_ecrire_martiales" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_martiales" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Martiales> dans Joueur::trouver_interpreter_ecrire_martiales (" << contenu_balise << ") " << ouvrante_fermante << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_martiales" << endreq;
      exit(1);
    }
  func() << "Ecrire martiales -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/**************************************************************************//**
 *
 * Ecrit les sorts dans le tableau 'vec'
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
void Joueur::trouver_interpreter_ecrire_sorts(string& a, vector<Sort>& vec)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire sorts -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  unsigned int nbr1, nbr2, nbr3;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Sorts")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      nbr1 = read_int(a);
	      sauter_blanc(a);
	      nbr2 = read_int(a);
	      sauter_blanc(a);
	      nbr3 = read_int(a);
	      sauter_blanc(a);
	      lfunc() << nbr1 << ' ' << nbr2 << ' ' << nbr3 << endreq;
	      vec.push_back(Sort(nbr1, nbr2, nbr3));
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Sorts")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Sorts> dans Joueur::trouver_interpreter_ecrire_sorts" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_sorts" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Sorts> dans Joueur::trouver_interpreter_ecrire_sorts (" << contenu_balise << ") " << ouvrante_fermante << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_sorts" << endreq;
      exit(1);
    }
  func() << "Ecrire sorts -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Récupère le vector de TypeClasse
 *
 ******************************************************************************/

void Joueur::trouver_interpreter_ecrire_access(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire accès -> début" << endreq;
  char ouvrante_fermante;
  string contenu_balise;
  unsigned int nbr;
  trouver_o(a);
  contenu_balise=lit_balise(a, ouvrante_fermante);
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise == "Acces")
	{
	  sauter_blanc(a);
	  while (a[index]!='<')
	    {
	      nbr = read_int(a);
	      sauter_blanc(a);
	      J_CompAccess.push_back((TypeClasse)nbr);
	    }
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Acces")
		{}
	      // OK, rien à faire
	      else
		{
		  error() << "Balise supposée être </Acces> dans Joueur::trouver_interpreter_ecrire_acces" << endreq;
		  exit(1);
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_acces" << endreq;
	      exit(1);
	    }
	}
      else
	{
	  error() <<  "Balise supposée être <Acces> dans Joueur::trouver_interpreter_ecrire_acces (" << contenu_balise << ") " << ouvrante_fermante << endreq;
	  exit(1);
	}
    }
  else
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_acces" << endreq;
      exit(1);
    }
  func() << "Ecrire accès -> fin" << endreq;
  dout.setLevel(etat_precedent);
}

/******************************************************************************
 *
 * Ecrit le nombre de classes
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
int Joueur::trouver_interpreter_ecrire_nb(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire nb -> début" << endreq;
  trouver_o(a);
  int retour;
  char ouvrante_fermante;
  string contenu_balise(lit_balise(a, ouvrante_fermante));
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise=="Multi")
	{
	  sauter_blanc(a);
	  retour = read_int(a);
	  sauter_blanc(a);
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="Multi")
		{
		  func() << "Ecrire nb -> fin" << endreq;
		  dout.setLevel(etat_precedent);
		  return retour;
		}
	      else
		{
		  error() <<  "Balise supposée être </Multi> dans Joueur::trouver_interpreter_ecrire_nb" << endreq;
		  exit(1);;
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_nb" << endreq;
	      exit(1);
	    } 
	}
      else
	// Contenu erroné
	{
	  error() << "Balise supposée être <Multi> dans Joueur::trouver_interpreter_ecrire_nb" << endreq;
	  exit(1);
	}	
    }
  else
    // La balise n'est pas ouvrante
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_nb" << endreq;
      exit(1);
    }
}

/******************************************************************************
 *
 * Ecrit le nombre de PV du Joueur
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
int Joueur::trouver_interpreter_ecrire_PV(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire PV -> début" << endreq;
  trouver_o(a);
  int retour;
  char ouvrante_fermante;
  string contenu_balise(lit_balise(a, ouvrante_fermante));
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise=="PV")
	{
	  sauter_blanc(a);
	  retour = read_int(a);
	  sauter_blanc(a);
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="PV")
		{
		  func() << "Ecrire PV -> fin" << endreq;
		  dout.setLevel(etat_precedent);
		  return retour;
		}
	      else
		{
		  error() <<  "Balise supposée être </PV> dans Joueur::trouver_interpreter_ecrire_PV" << endreq;
		  exit(1);;
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_PV" << endreq;
	      exit(1);
	    } 
	}
      else
	// Contenu erroné
	{
	  error() << "Balise supposée être <PV> dans Joueur::trouver_interpreter_ecrire_PV (" << contenu_balise << " ) " << ouvrante_fermante << endreq;
	  exit(1);
	}	
    }
  else
    // La balise n'est pas ouvrante
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_PV" << endreq;
      exit(1);
    }
}

/******************************************************************************
 *
 * Ecrit le nombre de PP du Joueur
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
int Joueur::trouver_interpreter_ecrire_PP(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire PV -> début" << endreq;
  trouver_o(a);
  int retour;
  char ouvrante_fermante;
  string contenu_balise(lit_balise(a, ouvrante_fermante));
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise=="PP")
	{
	  sauter_blanc(a);
	  retour = read_int(a);
	  sauter_blanc(a);
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="PP")
		{
		  func() << "Ecrire PP -> fin" << endreq;
		  dout.setLevel(etat_precedent);
		  return retour;
		}
	      else
		{
		  error() <<  "Balise supposée être </PP> dans Joueur::trouver_interpreter_ecrire_PP" << endreq;
		  exit(1);;
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_PP" << endreq;
	      exit(1);
	    } 
	}
      else
	// Contenu erroné
	{
	  error() << "Balise supposée être <PP> dans Joueur::trouver_interpreter_ecrire_PP (" << contenu_balise << " ) " << ouvrante_fermante << endreq;
	  exit(1);
	}	
    }
  else
    // La balise n'est pas ouvrante
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_PP" << endreq;
      exit(1);
    }
}

/******************************************************************************
 *
 * Ecrit le nombre d'XPs du Joueur
 *
 * FUNC  permet d'afficher les messages de début et de fin
 *
 *****************************************************************************/
int Joueur::trouver_interpreter_ecrire_XP(string& a)
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction_recuperation_xml);
  func() << "Ecrire XP -> début" << endreq;
  trouver_o(a);
  int retour;
  char ouvrante_fermante;
  string contenu_balise(lit_balise(a, ouvrante_fermante));
  trouver_f(a);
  if (ouvrante_fermante=='o')
    {
      if (contenu_balise=="XP")
	{
	  sauter_blanc(a);
	  retour = read_int(a);
	  sauter_blanc(a);
	  trouver_o(a);
	  contenu_balise=lit_balise(a, ouvrante_fermante);
	  if (ouvrante_fermante=='f')
	    {
	      if (contenu_balise=="XP")
		{
		  func() << "Ecrire PV -> fin" << endreq;
		  dout.setLevel(etat_precedent);
		  return retour;
		}
	      else
		{
		  error() <<  "Balise supposée être </XP> dans Joueur::trouver_interpreter_ecrire_XP" << endreq;
		  exit(1);;
		}
	    }
	  else
	    // La balise n'est pas fermante
	    {
	      error() << "Balise non fermante dans Joueur::trouver_interpreter_ecrire_XP" << endreq;
	      exit(1);
	    } 
	}
      else
	// Contenu erroné
	{
	  error() << "Balise supposée être <XP> dans Joueur::trouver_interpreter_ecrire_XP" << endreq;
	  exit(1);
	}	
    }
  else
    // La balise n'est pas ouvrante
    {
      error() << "Pas de balise ouvrante dans Joueur::trouver_interpreter_ecrire_XP" << endreq;
      exit(1);
    }
}
